libvips / pyvips

python binding for libvips using cffi
MIT License
649 stars 50 forks source link

Error when merging 4 large images together #433

Closed AmazTING closed 1 year ago

AmazTING commented 1 year ago

I am attempting to stitch 4 quite large (86016x43008 each) images together, and am encountering an error.

import pyvips

image1 = pyvips.Image.new_from_file('3.png')
image2 = pyvips.Image.new_from_file('4.png')
image3 = pyvips.Image.new_from_file('2.png')
image4 = pyvips.Image.new_from_file('1.png')

images = [image1, image2, image3, image4]
top = pyvips.Image.arrayjoin(images[:2], across=2)
bottom = pyvips.Image.arrayjoin(images[2:], across=2)
final = pyvips.Image.arrayjoin([top, bottom], across=1)
final.write_to_file("final.png")

and I get the below error:

Traceback (most recent call last):
  File "C:\...\merger.py", line 13, in <module>
    final.write_to_file("final.png")
  File "C:\...\vimage.py", line 804, in write_to_file
    return pyvips.Operation.call(name, self, filename,
  File "C:\...\voperation.py", line 305, in call
    raise Error('unable to call {0}'.format(operation_name))
pyvips.error.Error: unable to call VipsForeignSaveSpngFile
  wbuffer_write: write failed
windows error: The printer is out of paper.

What does the error mean and is there an issue with my code?

jcupitt commented 1 year ago

Hi @AmazTING,

I would write your program like this:

import pyvips

image1 = pyvips.Image.new_from_file('3.png', access='sequential')
image2 = pyvips.Image.new_from_file('4.png', access='sequential')
image3 = pyvips.Image.new_from_file('2.png', access='sequential')
image4 = pyvips.Image.new_from_file('1.png', access='sequential')

final = pyvips.Image.arrayjoin([image1, image2, image3, image4], across=2)
final.write_to_file('final.png')

As for the error, I would guess final.png is just too big for PNG. Maybe try some other format? Tiled TIFF with deflate compression is close to PNG and has no size limit.

I would test with much smaller images first.

jcupitt commented 1 year ago

If that's all the processing you need to do, you can also do that arrayjoin from the command-line:

vips.exe arrayjoin "3.png 4.png 2.png 1.png" final.png --across 2 --vips-progress

And get a progress ticker too.

You could try:

vips.exe arrayjoin "3.png 4.png 2.png 1.png" final.tif[compression=deflate,tile] --across 2 --vips-progress

To experiment with deflate tiled tiff.

AmazTING commented 1 year ago

I attempted the second of the two command line options and received a different error:

TIFFAppendToStrip: Maximum TIFF file size exceeded vips2tiff: TIFF write tile failed wbuffer_write: write failed TIFFWriteDirectoryTagData: Maximum TIFF file size exceeded

AmazTING commented 1 year ago

Ok, I just had to enable the "bigtiff" option and it worked.

jcupitt commented 1 year ago

Great! I'm glad it worked.

You need to be slightly careful with deflate tiled tiff -- not every program will support this type of TIFF file.