1

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
Kingsley
  • 14,398
  • 5
  • 31
  • 53

1 Answers1

2

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")
jcupitt
  • 10,213
  • 2
  • 23
  • 39
  • Fixed it! Thanks for that. – Kingsley Nov 28 '18 at 05:34
  • Glad it's working. I tried to update the question you based this on as well. – jcupitt Nov 28 '18 at 05:35
  • 1
    For grayscale images (only one channel): `linear = image_matrix.astype(np.uint8).reshape(-1)` `im = pyvips.Image.new_from_memory(linear.data, image_matrix.shape[1], image_matrix.shape[0], bands=1, format="uchar")` `im.write_to_file('out.bmp')` – Samuel Prevost Mar 05 '19 at 13:32