Delphi 无法压缩JPEG图像并在屏幕上显示
我尝试在imgQInput(这是一个TImage)中加载一个图像,将其分配给一个TJPEG图像,压缩它(压缩因子5),并在imgQOutput(另一个TImage)中显示它。但它不起作用。imgQOutput中的图像与原始图像相同。它应该看起来非常像素化,因为压缩因子!但是,压缩可以工作,因为当我将JPEG保存到磁盘时,它非常小Delphi 无法压缩JPEG图像并在屏幕上显示,delphi,Delphi,我尝试在imgQInput(这是一个TImage)中加载一个图像,将其分配给一个TJPEG图像,压缩它(压缩因子5),并在imgQOutput(另一个TImage)中显示它。但它不起作用。imgQOutput中的图像与原始图像相同。它应该看起来非常像素化,因为压缩因子!但是,压缩可以工作,因为当我将JPEG保存到磁盘时,它非常小 JPG:= TJPEGImage.Create; TRY JPG.CompressionQuality:= trkQuality.Position;
JPG:= TJPEGImage.Create;
TRY
JPG.CompressionQuality:= trkQuality.Position;
JPG.Assign(imgQInput.Picture.Graphic);
CompressJpeg(JPG);
imgQOutput.Picture.Assign(JPG); <--------- something wrong here. the shown image is not the compressed image but the original one
FINALLY
FreeAndNil(JPG);
END;
function CompressJpeg(OutJPG: TJPEGImage): Integer;
VAR tmpQStream: TMemoryStream;
begin
tmpQStream:= TMemoryStream.Create;
TRY
OutJPG.Compress;
OutJPG.SaveToStream(tmpQStream);
OutJPG.SaveToFile('c:\CompTest.jpg'); <--------------- this works
Result:= tmpQStream.Size;
FINALLY
FreeAndNil(tmpQStream);
END;
end;
JPG:=TJPEGImage.Create;
尝试
JPG.压缩质量:=trkQuality.位置;
分配(imgQInput.Picture.Graphic);
压缩JPEG(JPG);
imgQOutput.Picture.Assign(JPG) 您根本没有使用压缩的JPG
更改压缩JPEG
,如下所示:
function CompressJpeg(OutJPG: TJPEGImage): Integer;
VAR tmpQStream: TMemoryStream;
begin
tmpQStream:= TMemoryStream.Create;
TRY
OutJPG.Compress;
OutJPG.SaveToStream(tmpQStream);
OutJPG.SaveToFile('c:\CompTest.jpg'); // You can remove this line.
tmpQStream.Position := 0; //
OutJPG.LoadFromStream(tmpQStream); // Reload the jpeg stream to OutJPG
Result:= tmpQStream.Size;
FINALLY
FreeAndNil(tmpQStream);
END;
end;
这里有一个与之竞争的答案,数据处理较少(请记住,图像可能很大!)
TJPEGImage.FreeBitmap
处理TJPEGImage实例中包含的易失性DIB。在图示的情况下,这会导致类最近解码。压缩“Eded JPEG,以响应TImage
重新绘制。TJpegImage保存位图DIB和JPEG数据,即使压缩有效且保存到文件/流保存压缩的JPEG,将其分配给TImage。Picture使用DIB,而不是将原始图像留给您,Vahid的回答有效,因为他已从流中重新加载JPeg,从而清除了DIB。谢谢Dampsquid。还有另一种方法可以不从流中重新加载它吗?像JPEG需要吗?我从来没有找到一个,DIBNeeded只在没有的情况下创建一个,分配给新的TJPegImage也会分配DIB,这样也不起作用。不客气。压缩/保存TJpegImage实例时,不会影响原始缓冲区。因此,您需要使用新创建的jpeg流重新加载OutJPG
,以更新缓冲区。所以,有些东西被改变了。@DavidHeffernan,错了,JPEG远远不仅仅是一个过滤器。事实上,这个类非常懒惰,直到人们每次试图争论他们不理解的事情时,JPEGNeeded
@DavidHeff,才执行编码;-)现在,您正在从“是”倒退到“可能”,现在请慢慢阅读JPEG压缩,以及为什么它不是流过滤器。否则,请解释您的兴趣,但请记住网站的口号-要具体。@DavidHeffernan,我告诉过您要具体,除了通常未公开给公共范围的方法来指示类丢失其自愿DIB数据之外,它没有什么棘手的地方。而且您仍然在重复错误的信息,Compress(公共的和有良好文档记录的!)方法指示类执行上述向量和矩阵变换。而且没有流。freebimat
部分做什么?(协商?)@user539484。您的答案似乎不错,但它遗漏了一点:它没有告诉压缩图像的大小。我的函数“CompressJpeg”会执行此操作。@user539484-此应用程序已泄漏内存。小数据块泄漏(不包括指针注册的预期泄漏):21-36字节:TJPEGData x 2,TMemoryStream x 2 69-84字节:TJPEGImage x2@Altar,已确认一个TJPEG图像/TJPEG数据对泄漏,其他在别处。
type
TJPEGExposed = class(TJPEGImage); // unfortunately, local class declarations are not allowed
procedure TForm1.FormClick(Sender: TObject);
var
JPEGImage: TJPEGImage;
const
jqCrappy = 1;
begin
Image1.Picture.Bitmap.LoadFromFile(GetDeskWallpaper);
Image2.Picture.Graphic := TJPEGImage.Create;
JPEGImage := Image2.Picture.Graphic as TJPEGImage; // a reference
JPEGImage.Assign(Image1.Picture.Bitmap);
JPEGImage.CompressionQuality := jqCrappy; // intentionally
JPEGImage.Compress;
TJPEGExposed(JPEGImage).FreeBitmap; { confer: TBitmap.Dormant }
end;