我需要调整巨大的(高达30000x30000)不使用RAM JPEG文件,速度无所谓,有没有办法这样做呢? 我尝试了不同的库(nativejpg等),但他们使用所有可用的RAM,并和崩溃中包含“内存不足”或错误“没有足够的存储是可用来处理此命令”。 我甚至尝试命令行实用程序ImageMagick的,但它也采用GB的内存。
Answer 1:
我建议你看看vips
。 据记载这里 。
我可以创建噪声的10000x10000像这样与ImageMagick的
convert -size 10000x10000! xc:gray50 +noise poisson image.jpg
并检查它是正确的大小是这样的:
identify image.jpg
image.jpg JPEG 10000x10000 10000x10000+0+0 8-bit sRGB 154.9MB 0.000u
我现在可以使用vips
向下调整10000x10000图像2500x2500这样的
time vipsthumbnail image.jpg -s 2500 -o small.jpg --vips-leak
memory: high-water mark 20.48 MB
real 0m1.974s
user 0m2.158s
sys 0m0.096s
注意内存使用量达到峰值,仅20MB
请像这样与ImageMagick的结果
identify result.jpg
result.jpg JPEG 2500x2500 2500x2500+0+0 8-bit sRGB 1.33MB 0.000u 0:00.000
看一看技术说明过,关于性能和内存使用- 在这里 。
您还可以调用它C
以及命令行。
Answer 2:
如果打开的libjpeg收缩载你可以用ImageMagick的做到这一点。 尝试:
$ identify big.jpg
big.jpg JPEG 30000x30000 30000x30000+0+0 8-bit sRGB 128MB 0.000u 0:00.000
$ time convert -define jpeg:size=2500x2500 big.jpg -resize 2500x2500 small.jpg
real 0m3.169s
user 0m2.999s
sys 0m0.159s
peak mem: 170MB
这是如何工作:libjpeg的有很大的收缩载功能。 当你打开一个图像,你可以要求该库由X2,X4或x8在加载过程中下采样 - 库然后只解码每个DCT块的一部分。
但是,此功能必须在图像打开时被启用,以后不能设置。 所以convert
需要一个暗示,当它打开big.jpg
,只需要得到至少尺寸2500x2500(目标大小)的图像。 现在,所有的-resize
做的是一个缩水像素3800x3800的图像到2500x2500,一个操作非常简单。 您只需要在CPU和内存的1/64。
作为@标记瑟特查上面说的, vipsthumbnail
还要快:
$ time vipsthumbnail big.jpg -s 2500 -o small.jpg --vips-leak
memory: high-water mark 29.93 MB
real 0m2.362s
user 0m2.873s
sys 0m0.082s
虽然加速不是很显着的,因为这两个系统其实只是调整3800 - > 2500。
如果您尝试TIF相反,你看到一个大的差异,因为没有可以使用收缩载窍门:
$ identify 360mp.tif
360mp.tif TIFF 18000x18000 18000x18000+0+0 8-bit sRGB 972MB 0.000u 0:00.000
$ time convert 360mp.tif -resize 2500 x.tif
peak mem: 2.8 GB
real 0m8.397s
user 0m25.508s
sys 0m1.648s
$ time vipsthumbnail 360mp.tif -o x.tif -s 2500 --vips-leak
memory: high-water mark 122.08 MB
real 0m2.583s
user 0m9.012s
sys 0m0.308s
现在vipsthumbnail
约4倍速度更快,只需要记忆的1/20。
Answer 3:
借助内置的德尔福支持JPEG,你可以加载重采样为更小的尺寸,而无需装载的内存过量使用大JPEG图像。
JPEG图像缩放属性可以有以下值jsFullSize
, jsHalf
, jsQuarter
, jsEighth
procedure ScaleJpg(const Source, Dest: string);
var
SourceImg, DestImg: TJPEGImage;
Bmp: TBitmap;
begin
Bmp := TBitmap.Create;
try
SourceImg := TJPEGImage.Create;
try
SourceImg.Scale := jsEighth;
SourceImg.LoadFromFile(Source);
Bmp.Width := SourceImg.Width;
Bmp.Height := SourceImg.Height;
Bmp.Canvas.Draw(0, 0, SourceImg);
finally
SourceImg.Free;
end;
DestImg := TJPEGImage.Create;
try
DestImg := TJPEGImage.Create;
DestImg.Assign(Bmp);
DestImg.SaveToFile(Dest);
finally
DestImg.Free;
end;
finally
Bmp.Free;
end;
end;
一旦你已经大致重新缩放图像到可以在内存中处理舒适的尺寸就可以申请普通的缩放算法,以获得您想要的实际图像大小。