简体   繁体   English

低内存图像调整大小

[英]Low memory image resizing

I am looking for some advice on how to construct a very low memory image resizing program that will be run as a child process of my nodejs application in linux. 我正在寻找有关如何构建内存非常低的图像大小调整程序的建议,该程序将作为我的nodejs应用程序在Linux中的子进程运行。

The solution I am looking for is a linux executable that will take a base64 string image (uploaded from a client) using stdin, resizing the photo to a specified size and then pumping the resulting image data back through stdout. 我正在寻找的解决方案是一个Linux可执行文件,它将使用stdin提取base64字符串图像(从客户端上传),将照片调整为指定大小,然后将结果图像数据通过stdout抽回。

I've looked into image magick and it might be what I end up using, but I figured I would ask and see if anyone had a suggestion. 我研究了图像魔术 ,这可能是我最终使用的图像,但是我想我会问问是否有人提出建议。

Suggestions of libraries or examples of pre compiled executables in C/C++ would be greatly appreciated. 图书馆的建议或C / C ++中预编译的可执行文件的示例将不胜感激。 Also a helpful answer would include general strategies for low memory image resizing. 同样有用的答案将包括降低内存图像大小的一般策略。

Thank you 谢谢

Depending on the image formats you want to support, it's almost surely possible to perform incremental decoding and scaling by decoding only a few lines at a time and discarding the data once you write the output. 根据您要支持的图像格式,几乎肯定可以通过一次解码仅几行并在写入输出后丢弃数据来执行增量解码和缩放。 However it may require writing your own code or adapting an existing decoder library to support this kind of operation. 但是,可能需要编写自己的代码或改编现有的解码器库以支持这种操作。

It's also worth noting that downsizing giant jpegs can be performed efficiently by simply skipping the high-frequency coefficients and using a smaller IDCT. 还要注意的是,只需跳过高频系数并使用较小的IDCT,就可以有效地减小巨型jpeg的大小。 For example, to decode at half width and half height, discard all but the upper-left quadrant of the coefficients (horizontal and vertical frequency < 4) and use a 4x4 IDCT on them instead of the usual 8x8. 例如,要以一半的宽度和一半的高度进行解码,请丢弃系数的左上象限以外的所有象素(水平和垂直频率<4),并在其上使用4x4 IDCT,而不是通常的8x8。 Both the libjpeg decoder and the libavcodec decoder support this operation for power-of-2 scalings (1/2, 1/4, or 1/8). libjpeg解码器和libavcodec解码器均支持2幂次缩放(1 / 2、1 / 4或1/8)的此操作。 This type of approach might make incremental decoding/scaling unnecessary. 这种类型的方法可能不需要进行增量解码/缩放。

You can try it out with djpeg -scale 1/4 < src.jpg | cjpeg > dest.jpg 您可以使用djpeg -scale 1/4 < src.jpg | cjpeg > dest.jpg djpeg -scale 1/4 < src.jpg | cjpeg > dest.jpg . djpeg -scale 1/4 < src.jpg | cjpeg > dest.jpg If you want a fixed output size, you'll probably first scale by whichever of 1/2, 1/4, or 1/8 puts you closest to the desired size without going to low, then performing interpolation to go the final step, eg djpeg -scale 1/4 < src.jpg | convert pnm:- -scale 640x480 dest.jpg 如果您想要固定的输出尺寸,则可能会先以1 / 2、1 / 4或1/8中的任意一个比例缩放,以使您最接近所需的尺寸而不会变小,然后执行插值操作进行最后一步,例如djpeg -scale 1/4 < src.jpg | convert pnm:- -scale 640x480 dest.jpg djpeg -scale 1/4 < src.jpg | convert pnm:- -scale 640x480 dest.jpg . djpeg -scale 1/4 < src.jpg | convert pnm:- -scale 640x480 dest.jpg

When working on very large images, such as 0.25 GPix and larger, ImageMagick uses ~2 GB ram, even when using djpeg to decode the JPEG image first. 当处理非常大的图像(例如0.25 GPix和更大的图像)时,即使先使用djpeg解码JPEG图像,ImageMagick也使用〜2 GB内存。

This command chain will resize JPEG images of about any size using only ~3 MB ram: 该命令链将仅使用〜3 MB ram来调整大约任何大小的JPEG图像的大小:

djpeg my-large.jpg | pnmscale -xysize 16000 16000 | cjpeg > scaled-large.jpg

GraphicsMagick is generally a better version of ImageMagick, I'd take a look at that. 通常,GraphicsMagick是ImageMagick的更好版本,我来看一下。 If you really need something fast, you probably want to drop to something like libjpeg - while you say you want something that's non-blocking IO, the operation you want to do is relatively CPU-bound (ie decoding the image, then trying to resize it). 如果您确实需要快速执行某些操作,则可能希望使用libjpeg之类的文件-当您说需要非阻塞IO时,您要执行的操作是相对CPU密集的(即解码图像,然后尝试调整大小)它)。

if anything this is just a sample following what he described: 如果有的话,这只是他描述的一个样本:

import sys
from PIL import Image
import binascii
import cStringIO
x,y = sys.stdin.readline().strip().split(' ')
x,y = int(x), int(y)
img = Image.open(cStringIO.StringIO(binascii.b2a_base64(sys.stdin.read())).resize(x,y)
img.save(sys.stdout, format="png")

as that has to read the input, decode it, resize, and encode, and write it out there is no way to reduce the size of the memory used to less then the size of the input image 因为必须读取输入,对其进行解码,调整大小以及对其进行编码,然后将其写出,所以无法将所使用的内存大小减小到小于输入图像的大小

Nothing can beat Intel Integrated Performance Primitives in terms of performance. 在性能方面,没有任何东西可以击败英特尔集成性能基元。 If you can afford it I strongly recommend to use it. 如果您负担得起,我强烈建议您使用它。

Otherwise just implement your own resizing routine. 否则,只需实现自己的调整大小例程即可。 Lanczos gives quite good results albeit it won't be tremendously fast. Lanczos可以提供很好的结果,尽管它不会很快。

Edit: I strongly suggest you NOT to use Image Magick or Graphics Magick. 编辑:我强烈建议您不要使用Image Magick或Graphics Magick。 They are both great libraries, but designed for completely different purpose - handling many file formats, depths, pixel formats, etc. They sacrifice performance and memory effectiveness for the things I've mentioned. 它们都是很棒的库,但是为完全不同的目的而设计-处理许多文件格式,深度,像素格式等。它们为我提到的内容牺牲了性能和内存效率。

You might need this: https://github.com/zhangyuanwei/node-images 您可能需要此: https : //github.com/zhangyuanwei/node-images

Cross-platform image decoder(png/jpeg/gif) and encoder(png/jpeg) for Nodejs 适用于Node.js的跨平台图像解码器(png / jpeg / gif)和编码器(png / jpeg)

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM