How can I crop a big JPG and extract a small portion of it? The problem is main JPGs are so big and I can't load all of it in memory. I used convert.exe from ImageMagick, but it's not working properly on all versions of windows and I prefer some C# method instead of a standalone exe.
Cropping a JPG without loading all of it in memory
680 views Asked by AVEbrahimi AtThere are 3 answers
All Jpeg decoders I have seen first dump the Jpeg into memory and then start decoding. This is because of the nature of Jpeg format which is unlike a Bitmap you can not calculate file location for a pixel.
If you decide not to load into memory, then you have numerous file seeks, which makes your decoder less memory-intensive, but more I/O intensive.
The NanoJpeg project is a good start https://github.com/Deathspike/NanoJPEG.NET/blob/master/NanoJPEG.cs
There are a couple of possibilities. You could use stream
which is part of ImageMagick, or vips
. Let's do stream
first.
I can make a large (10,000x5,000) JPEG like this:
convert -size 10000x5000 xc:blue BigBoy.jpg
then use stream
like this to extract a chunk 1,000x1,000 from an offset of 8,000+50
stream -extract 1000x1000+8000+50 BigBoy.jpg extract.rgb
and the extraact.rgb
file is 3000000 bytes in size, i.e. 1,000x1,000 at 3 bytes/pixel.
If I do that with time -l
you can see the resident set is small despite the large image
/usr/bin/time -l stream -extract 1000x1000+8000+50 BigBoy.jpg extract.rgb
0.81 real 0.79 user 0.01 sys
2924544 maximum resident set size <----- 2MB RAM ****
0 average shared memory size
0 average unshared data size
0 average unshared stack size
796 page reclaims
You can then convert that extract.rgb
to JPEG with convert
convert -size 1000x1000 -depth 8 extract.rgb chunk.jpg
I am no expert on vips
, but you may have some success with this command that also shows the peak memory usage with the --vips-leak
flag at the end
vips extract_area BigBoy.jpg SmallBoy.jpg 8000 50 1000 1000 --vips-leak
memory: high-water mark 8.72 MB
I found a command line solution which does not depend on external libraries, jpegtran.
You can have jpegtran.exe beside your main exe and call it with these parameters:
Download jpegtran from here: http://jpegclub.org/jpegtran/