How can I append 2 BIG images using Marvin java library(or any other free lib)?

146 views Asked by At

I have 2 jpegs, about 16 000 x 24 000 px. I have to rotate the second and append it on top of the first, something like this

enter image description here .

I've found in the docs how to rotate (MarvinImage.rotate) but i haven't found a method that can append the 2 images.

Also, any suggestions of other libraries that can do this is also greatly appreciated. What I've tried until now:

  • BufferedImage and ImageIO: takes a whole lot of memory, would probably work if the write would work (JPEGImageWriter basically complains about the image being too big - integer overflow)

  • ImageMagick and im4java - works but terribly slow (13 minutes and 100% disk usage)

Thanks!

Bogdan

2

There are 2 answers

0
fmw42 On

In ImageMagick 6, that is easy to do.

Input 1 (lena.jpg):

enter image description here

Input 2 (mandril3.jpg):

enter image description here

Unix Syntax:

convert lena.jpg \( mandril3.jpg -rotate 180 \) +swap -append result.jpg


enter image description here

For Windows syntax, remove the \s. For ImageMagick 7, replace convert with magick.

ImageMagick comes with Linux distributions. It is also available for Mac OSX and Windows.

0
jcupitt On

libvips can do this quickly and in little memory, but unfortunately there's no convenient Java binding. You'd need to write a few lines using something like pyvips and then shell out to that.

For example:

import sys
import pyvips

one = pyvips.Image.new_from_file(sys.argv[1])
two = pyvips.Image.new_from_file(sys.argv[2], access='sequential')
one.rot180().join(two, 'vertical').write_to_file(sys.argv[3])

The access= hint on new_from_file in two means we plan to read the second image top-to-bottom, ie. in the same order that pixels appear in the jpg file. This will let libvips stream that image, so it can overlap the decode of two with the write of the output image.

On this 2015 laptop, I see:

$ vipsheader ~/pics/top.jpg ~/pics/bot.jpg
/home/john/pics/top.jpg: 16000x24000 uchar, 3 bands, srgb, jpegload
/home/john/pics/bot.jpg: 16000x24000 uchar, 3 bands, srgb, jpegload
$ /usr/bin/time -f %M:%e ./join.py ~/pics/top.jpg ~/pics/bot.jpg x.jpg
115236:27.85
$ vipsheader x.jpg 
x.jpg: 16000x48000 uchar, 3 bands, srgb, jpegload

So a peak of 115MB of memory, and it runs in 28s of real time.

That will create a temporary file for one so it can do the rotate. If you are OK using a lot of memory, you can try:

one = pyvips.Image.new_from_file(sys.argv[2], memory=True)

That will force libvips to open via a memory area. I now see:

$ /usr/bin/time -f %M:%e ./join.py ~/pics/top.jpg ~/pics/bot.jpg x.jpg
1216812:14.53

Only 15s of real time, but a painful 1.2GB peak memory use.