裁剪JPG而不将所有内容加载到内存中

时间:2015-06-25 04:55:02

标签: c# image crop imagemagick-convert

如何裁剪大型JPG并提取一小部分? 问题是主要的JPG是如此之大,我无法将所有内容加载到内存中。 我使用了ImageMagick的convert.exe,但它在所有版本的Windows上都不能正常工作,我更喜欢一些C#方法而不是一个独立的exe。

3 个答案:

答案 0 :(得分:3)

有几种可能性。您可以使用属于ImageMagick的streamvips。让我们先stream

我可以像这样制作一个大的(10,000x5,000)JPEG:

convert -size 10000x5000 xc:blue BigBoy.jpg

然后像这样使用stream从偏移量8,000 + 50

中提取1,000x1,000块
stream -extract 1000x1000+8000+50 BigBoy.jpg extract.rgb

extraact.rgb文件的大小为3000000字节,即3字节/像素为1,000x1,000。

如果我使用time -l执行此操作,您可以看到尽管图像较大,驻留集仍然很小

/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

然后,您可以使用extract.rgb

convert转换为JPEG
convert -size 1000x1000 -depth 8 extract.rgb chunk.jpg

我不是vips的专家,但您可能会在此命令中取得一些成功,该命令还会显示最终的--vips-leak标记的峰值内存使用情况

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

答案 1 :(得分:1)

我见过的所有Jpeg解码器首先将Jpeg转储到内存中然后开始解码。这是因为Jpeg格式的性质与Bitmap不同,您无法计算像素的文件位置。

如果您决定不加载到内存中,那么您需要进行大量文件搜索,这会使您的解码器内存不足,但I / O密集程度更高。

NanoJpeg项目是一个良好的开端 https://github.com/Deathspike/NanoJPEG.NET/blob/master/NanoJPEG.cs

答案 2 :(得分:0)

我找到了一个不依赖外部库的命令行解决方案, jpegtran

您可以在主exe旁边使用 jpegtran.exe 并使用以下参数调用它:

jpegtran -crop WxH+X+Y input_file output_file

从这里下载 jpegtran http://jpegclub.org/jpegtran/