pythonnumpyvips

Create Vips Image from Numpy RGB array for big images


I was trying to output a large, generated image with PIL/Pillow, but it breaks when the image sizes get bigger.

So based on things I read on SO, I'm trying to use Vips.

My generated data is a numpy array of RGB values. I want to convert this to a image in Vips so I can save it. However I cannot work out how to get the pixel data into Vips.

import numpy
import gi
gi.require_version('Vips', '8.0')
from gi.repository import Vips

WIDTH=32768
HEIGHT=32768
UCHAR=Vips.BandFormat.UCHAR

# Create an RGB black image
black_space = numpy.zeros( ( WIDTH, HEIGHT, 3 ), dtype=numpy.uint8 )

# this doesn't work
vips_image = Vips.Image.new_from_memory( black_space, WIDTH, HEIGHT, bands=3, format=UCHAR )
vips_image.write_to_file( "space_32k.tiff" )

Of course it fails with the error when creating the Vips image:

Traceback (most recent call last):
  File "./bad_vips.py", line 14, in <module>
    vips_image = Vips.Image.new_from_memory( black_space, WIDTH, HEIGHT, bands=3, format=UCHAR )
TypeError: Item 0: expected int argument

Is there a way of transforming the numpy array so it works with Vips?

I also tried passing black_space.data, but then I get:

NotImplementedError: Item 0: multi-dimensional sub-views are not implemented

Solution

  • You're using the old libvips Python interface -- there's a newer one now which is quite a bit better:

    https://github.com/libvips/pyvips

    Docs here:

    https://libvips.github.io/pyvips/

    There's a section about linking libvips and numpy. Your example would be:

    import numpy as np
    import pyvips
        
    array = np.zeros((100, 100, 3), dtype=np.uint8)
    image = pyvips.Image.new_from_array(array)
    image.write_to_file("huge.tif")