Trim JPG without loading everything into memory

How can I crop a large JPG and extract a small portion? The problem is that the underlying JPGs are so big that I can't load the whole thing into memory. I used convert.exe from ImageMagick but it doesn't work as expected on all Windows versions and I prefer some kind of C # method instead of a standalone exe.

-1


source to share


3 answers


I found a command line solution that does not depend on external libraries, jpegtran .

You can have jpegtran.exe next to your main exe and call it using these options:



jpegtran -crop WxH+X+Y input_file output_file

      

Download jpegtran from here: http://jpegclub.org/jpegtran/

0


source


There are several possibilities. You can use stream

which is part of ImageMagick or vips

. Let's do it first stream

.

I can make a large (10,000x5,000) JPEG like this:

convert -size 10000x5000 xc:blue BigBoy.jpg

      

then use stream

to extract a 1,000x1,000 chunk from offset 8000 + 50

stream -extract 1000x1000+8000+50 BigBoy.jpg extract.rgb

      

and the file extraact.rgb

is 3,000,000 bytes in size, i.e. 1000x1000 with 3 bytes / pixel.



If I do this with time -l

, you can see that 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

      

Then you can convert this extract.rgb

to JPEG withconvert

convert -size 1000x1000 -depth 8 extract.rgb chunk.jpg

      

I am not an expert on vips

, but you can succeed with this command which also shows peak memory usage with a flag --vips-leak

at the end

vips extract_area BigBoy.jpg SmallBoy.jpg 8000 50 1000 1000 --vips-leak
memory: high-water mark 8.72 MB

      

+3


source


All Jpeg decoders I've seen dump the Jpeg into memory first and then start decoding. This is due to the nature of the Jpeg format, which is different from Bitmap, you cannot calculate the file location for the pixel.

If you choose not to load into memory, you have many files that make 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

+1


source







All Articles