Reputation: 1592
Is there a way to crop an image without having the load the entire image into memory and cropping it then?
The scenario is that I have a really really big image file and I have a list of rectangular coordinates that I need to crop out of the big image. The image is so huge I can't directly load it into memory. Is there a technique I can stream the image and sort of find the start and end points to crop? Don't mind if I have to perform this step many times for each set of coordinates. Oh yeah, assuming the images are of format JPG/PNG/TIFF which ever one is easiest to work with.
Should be able to run on Windows and Linux should there be any dependencies on native libraries.
Thanks.
Upvotes: 2
Views: 1036
Reputation: 208052
You can use libvips
to do this - it is available for Linux, OSX and Windows.
To get set up, let's use ImageMagick to create a big image (10,000x10,000) that is difficult to compress because it is full of random noise:
convert -size 10000x10000 xc:gray +noise random \
-fill red -draw "rectangle 0,0 100,100" \
-fill blue -draw "rectangle 9900,9900 10000,10000" BigBoy.tif
Reduced in size, it looks like this, with a red rectangle in the top-left and a blue rectangle in the bottom-right if you look closely:
and weighs in at 800 MB:
-rw-r--r--@ 1 mark staff 800080278 5 May 12:08 BigBoy.tif
Now let's use libvips
(just at the command-line) to extract the top-left and bottom-right corners (which are readily identifiable - did you see what I did there?):
vips im_extract_area BigBoy.tif topleft.jpg 0 0 200 200 --vips-leak
memory: high-water mark 118.85 MB
vips im_extract_area BigBoy.tif bottomright.jpg 9800 9800 200 200 --vips-leak
memory: high-water mark 118.85 MB
Both commands used around 120MB of memory. I don't believe there are Java bindings for libvips
, but I presume you can fork()
and exec()
stuff or use something like C's system()
function.
Upvotes: 1