2017-04-07 16:59:37 +02:00
<?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">
2022-06-15 11:19:49 +02:00
<refentry id= "Examples" >
2017-04-07 16:59:37 +02:00
<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. It’ s also a useful source of examples.
</para>
2020-08-09 15:21:26 +02:00
<refsect3 xml:id= "average-a-region-of-interest-box-on-an-image" >
2017-04-07 16:59:37 +02:00
<title > Average a region of interest box on an image</title>
<programlisting language= "python" >
2020-12-22 15:31:08 +01:00
#!/usr/bin/python3
2017-04-07 16:59:37 +02:00
import sys
2017-11-26 18:45:04 +01:00
import pyvips
2017-04-07 16:59:37 +02:00
left = 10
top = 10
width = 64
height = 64
2017-11-26 18:45:04 +01:00
image = pyvips.Image.new_from_file(sys.argv[1])
2017-04-07 16:59:37 +02:00
roi = image.crop(left, top, width, height)
2020-12-22 15:31:08 +01:00
print('average:', roi.avg())
2017-04-07 16:59:37 +02:00
</programlisting>
</refsect3>
2020-08-09 15:21:26 +02:00
<refsect3 xml:id= "libvips-and-numpy" >
2017-04-07 16:59:37 +02:00
<title > libvips and numpy</title>
<para >
2017-11-26 18:45:04 +01:00
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.
2017-04-07 16:59:37 +02:00
</para>
<programlisting language= "python" >
2020-12-22 15:31:08 +01:00
#!/usr/bin/python3
2017-04-07 16:59:37 +02:00
import sys
2017-11-26 18:45:04 +01:00
import time
2017-04-07 16:59:37 +02:00
2017-11-26 18:45:04 +01:00
import pyvips
from PIL import Image
import numpy as np
2017-04-07 16:59:37 +02:00
2017-11-26 18:45:04 +01:00
if len(sys.argv) != 3:
2020-12-22 15:31:08 +01:00
print(f'usage: {sys.argv[0]} input-filename output-filename')
2017-11-26 18:45:04 +01:00
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])
2017-04-07 16:59:37 +02:00
</programlisting>
</refsect3>
2020-08-09 15:21:26 +02:00
<refsect3 xml:id= "build-huge-image-mosaic" >
2017-04-07 16:59:37 +02:00
<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: it’ ll 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 >
$ 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 >
$ 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 >
2020-12-22 15:31:08 +01:00
$ time python try255.py x.tif[squash,compression=ccittfax4,strip,bigtiff] test/*
2017-04-07 16:59:37 +02:00
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, you’ d need to do some more work to convert them all into the same colourspace before inserting them.
</para>
<programlisting language= "python" >
2020-12-22 15:31:08 +01:00
#!/usr/bin/python3
#file try255.py
2017-04-07 16:59:37 +02:00
import sys
import random
2017-11-26 18:45:04 +01:00
import pyvips
2017-04-07 16:59:37 +02:00
# this makes a 8-bit, mono image of 100,000 x 100,000 pixels, each pixel zero
2017-11-26 18:45:04 +01:00
im = pyvips.Image.black(100000, 100000)
2017-04-07 16:59:37 +02:00
for filename in sys.argv[2:]:
2017-11-26 18:45:04 +01:00
tile = pyvips.Image.new_from_file(filename, access='sequential')
2017-04-07 16:59:37 +02:00
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>