libvips/doc/Examples.xml
Kleis Auke Wolthuizen fa03989b60
Minor doc improvements (#3202)
* doc: avoid use of GCC's old syntax (`-Wgnu-designator`)

* doc: highlight shell commands

* doc: point the C++ docs to v8.12

* doc: avoid highlight on output matching bash keywords
2022-11-30 00:07:57 +00:00

173 lines
5.5 KiB
XML
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

<?xml version="1.0" encoding="utf-8" ?>
<!DOCTYPE article PUBLIC "-//OASIS//DTD DocBook XML V4.5//EN"
"http://www.oasis-open.org/docbook/xml/4.5/docbookx.dtd">
<refentry id="Examples">
<para>
<refmeta> <refentrytitle>Examples</refentrytitle> <manvolnum>3</manvolnum> <refmiscinfo>libvips</refmiscinfo> </refmeta>
</para>
<para>
<refnamediv> <refname>libvips examples</refname> <refpurpose>A few example Python programs using libvips</refpurpose> </refnamediv>
</para>
<para>
This page shows a few libvips examples using Python. They will work with small syntax changes in any language with a libvips binding.
</para>
<para>
The libvips test suite is written in Python and exercises every operation in the API. Its also a useful source of examples.
</para>
<refsect3 xml:id="average-a-region-of-interest-box-on-an-image">
<title>Average a region of interest box on an image</title>
<programlisting language="python">
#!/usr/bin/python3
import sys
import pyvips
left = 10
top = 10
width = 64
height = 64
image = pyvips.Image.new_from_file(sys.argv[1])
roi = image.crop(left, top, width, height)
print('average:', roi.avg())
</programlisting>
</refsect3>
<refsect3 xml:id="libvips-and-numpy">
<title>libvips and numpy</title>
<para>
You can use <literal>pyvips.Image.new_from_memory()</literal> to make a vips image from an area of memory. The memory array needs to be laid out band-interleaved, as a set of scanlines, with no padding between lines.
</para>
<programlisting language="python">
#!/usr/bin/python3
import sys
import time
import pyvips
from PIL import Image
import numpy as np
if len(sys.argv) != 3:
print(f'usage: {sys.argv[0]} input-filename output-filename')
sys.exit(-1)
# map vips formats to np dtypes
format_to_dtype = {
'uchar': np.uint8,
'char': np.int8,
'ushort': np.uint16,
'short': np.int16,
'uint': np.uint32,
'int': np.int32,
'float': np.float32,
'double': np.float64,
'complex': np.complex64,
'dpcomplex': np.complex128,
}
# map np dtypes to vips
dtype_to_format = {
'uint8': 'uchar',
'int8': 'char',
'uint16': 'ushort',
'int16': 'short',
'uint32': 'uint',
'int32': 'int',
'float32': 'float',
'float64': 'double',
'complex64': 'complex',
'complex128': 'dpcomplex',
}
# load with PIL
start_pillow = time.time()
pillow_img = np.asarray(Image.open(sys.argv[1]))
print('Pillow Time:', time.time()-start_pillow)
print('original shape', pillow_img.shape)
# load with vips to a memory array
start_vips = time.time()
img = pyvips.Image.new_from_file(sys.argv[1], access='sequential')
mem_img = img.write_to_memory()
# then make a numpy array from that buffer object
np_3d = np.ndarray(buffer=mem_img,
dtype=format_to_dtype[img.format],
shape=[img.height, img.width, img.bands])
print('Vips Time:', time.time()-start_vips)
print('final shape', np_3d.shape)
# verify we have the same result
print('Sum of the Differences:', np.sum(np_3d-pillow_img))
# make a vips image from the numpy array
height, width, bands = np_3d.shape
linear = np_3d.reshape(width * height * bands)
vi = pyvips.Image.new_from_memory(linear.data, width, height, bands,
dtype_to_format[str(np_3d.dtype)])
# and write back to disc for checking
vi.write_to_file(sys.argv[2])
</programlisting>
</refsect3>
<refsect3 xml:id="build-huge-image-mosaic">
<title>Build huge image mosaic</title>
<para>
This makes a 100,000 x 100,000 black image, then inserts all the images you pass on the command-line into it at random positions. libvips is able to run this program in sequential mode: itll open all the input images at the same time, and stream pixels from them as it needs them to generate the output.
</para>
<para>
To test it, first make a large 1-bit image. This command will take the green channel and write as a 1-bit fax image. <literal>wtc.jpg</literal> is a test 10,000 x 10,000 jpeg:
</para>
<programlisting language="bash">
$ vips extract_band wtc.jpg x.tif[squash,compression=ccittfax4,strip] 1
</programlisting>
<para>
Now make 1,000 copies of that image in a subdirectory:
</para>
<programlisting language="bash">
$ mkdir test
$ for i in {1..1000}; do cp x.tif test/$i.tif; done
</programlisting>
<para>
And run this Python program on them:
</para>
<programlisting language="bash">
$ time python try255.py x.tif[squash,compression=ccittfax4,strip,bigtiff] test/*
real 1m59.924s
user 4m5.388s
sys 0m8.936s
</programlisting>
<para>
It completes in just under two minutes on this laptop, and needs about 7gb of RAM to run. It would need about the same amount of memory for a full-colour RGB image, I was just keen to keep disc usage down.
</para>
<para>
If you wanted to handle transparency, or if you wanted mixed CMYK and RGB images, youd need to do some more work to convert them all into the same colourspace before inserting them.
</para>
<programlisting language="python">
#!/usr/bin/python3
#file try255.py
import sys
import random
import pyvips
# this makes a 8-bit, mono image of 100,000 x 100,000 pixels, each pixel zero
im = pyvips.Image.black(100000, 100000)
for filename in sys.argv[2:]:
tile = pyvips.Image.new_from_file(filename, access='sequential')
im = im.insert(tile,
random.randint(0, im.width - tile.width),
random.randint(0, im.height - tile.height))
im.write_to_file(sys.argv[1])
</programlisting>
</refsect3>
</refentry>