裁剪 JPG 而不将其全部加载到内存中
Cropping a JPG without loading all of it in memory
如何裁剪大的 JPG 并提取其中的一小部分?
问题是主要的 JPG 文件太大,我无法将它们全部加载到内存中。
我使用了 ImageMagick 的 convert.exe,但它不能在所有版本的 windows 上正常工作,我更喜欢一些 C# 方法而不是独立的 exe。
我见过的所有Jpeg解码器都是先将Jpeg转存到内存中,然后再开始解码。这是因为 Jpeg 格式的性质与位图不同,您无法计算像素的文件位置。
如果您决定不加载到内存中,那么您会进行多次文件查找,这会使您的解码器占用更少的内存,但会增加 I/O 密集度。
NanoJpeg 项目是一个好的开始
https://github.com/Deathspike/NanoJPEG.NET/blob/master/NanoJPEG.cs
有两种可能性。您可以使用 stream
,它是 ImageMagick 的一部分,或者 vips
。让我们先做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 bytes/pixel.
处的 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
然后您可以使用 convert
将 extract.rgb
转换为 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
我找到了一个不依赖于外部库的命令行解决方案,jpegtran。
您可以在主 exe 旁边添加 jpegtran.exe 并使用这些参数调用它:
jpegtran -crop WxH+X+Y input_file output_file
从这里下载 jpegtran:
http://jpegclub.org/jpegtran/
如何裁剪大的 JPG 并提取其中的一小部分? 问题是主要的 JPG 文件太大,我无法将它们全部加载到内存中。 我使用了 ImageMagick 的 convert.exe,但它不能在所有版本的 windows 上正常工作,我更喜欢一些 C# 方法而不是独立的 exe。
我见过的所有Jpeg解码器都是先将Jpeg转存到内存中,然后再开始解码。这是因为 Jpeg 格式的性质与位图不同,您无法计算像素的文件位置。
如果您决定不加载到内存中,那么您会进行多次文件查找,这会使您的解码器占用更少的内存,但会增加 I/O 密集度。
NanoJpeg 项目是一个好的开始 https://github.com/Deathspike/NanoJPEG.NET/blob/master/NanoJPEG.cs
有两种可能性。您可以使用 stream
,它是 ImageMagick 的一部分,或者 vips
。让我们先做stream
。
我可以像这样制作大 (10,000x5,000) JPEG:
convert -size 10000x5000 xc:blue BigBoy.jpg
然后像这样使用 stream
从偏移量 8,000+50
stream -extract 1000x1000+8000+50 BigBoy.jpg extract.rgb
并且 extraact.rgb
文件的大小为 3000000 字节,即 3 bytes/pixel.
如果我用 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
然后您可以使用 convert
extract.rgb
转换为 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
我找到了一个不依赖于外部库的命令行解决方案,jpegtran。
您可以在主 exe 旁边添加 jpegtran.exe 并使用这些参数调用它:
jpegtran -crop WxH+X+Y input_file output_file
从这里下载 jpegtran: http://jpegclub.org/jpegtran/