【发布时间】:2012-05-11 21:50:09
【问题描述】:
当我搜索“JPEG”和“元数据”这两个词时,我有很多操作元数据的答案...而我想要的恰恰相反... ;o)
我编写了一个完全符合我要求的函数...(如果图像相似,并且只有元数据发生变化,则该函数返回 True ;如果至少有一个像素发生变化,则返回 False ) 但是,我想提高性能...
瓶颈是bmp.Assign(jpg);
function CompareImages(fnFrom, fnTo: TFileName): Boolean;
var
j1, j2: TJpegImage;
b1, b2: TBitmap;
s1, s2: TMemoryStream;
begin
Result := False;
sw1.Start;
j1 := TJpegImage.Create;
j2 := TJpegImage.Create;
sw1.Stop;
sw2.Start;
s1 := TMemoryStream.Create;
s2 := TMemoryStream.Create;
sw2.Stop;
//sw3.Start;
b1 := TBitmap.Create;
b2 := TBitmap.Create;
//sw3.Stop;
try
sw1.Start;
j1.LoadFromFile(fnFrom);
j2.LoadFromFile(fnTo);
sw1.Stop;
// the very long part...
sw3.Start;
b1.Assign(j1);
b2.Assign(j2);
sw3.Stop;
sw4.Start;
b1.SaveToStream(s1);
b2.SaveToStream(s2);
sw4.Stop;
sw2.Start;
s1.Position := 0;
s2.Position := 0;
sw2.Stop;
sw5.Start;
Result := IsIdenticalStreams(s1, s2);
sw5.Stop;
finally
// sw3.Start;
b1.Free;
b2.Free;
// sw3.Stop;
sw2.Start;
s1.Free;
s2.Free;
sw2.Stop;
sw1.Start;
j1.Free;
j2.Free;
sw1.Stop;
end;
end;
sw1, ..., sw5 是TStopWatch,我用来识别花费的时间。
IsIdenticalStreams 来自here。
如果我直接比较TJpegImage,流不一样...
有更好的编码方式吗?
问候,
W.
更新:
测试从 cmets 中提取的一些解决方案,我使用此代码具有相同的性能:
type
TMyJpeg = class(TJPEGImage)
public
function Equals(Graphic: TGraphic): Boolean; override;
end;
...
function CompareImages(fnFrom, fnTo: TFileName): Boolean;
var
j1, j2: TMyJpeg;
begin
sw1.Start;
Result := False;
j1 := TMyJpeg.Create;
j2 := TMyJpeg.Create;
try
j1.LoadFromFile(fnFrom);
j2.LoadFromFile(fnTo);
Result := j1.Bitmap.Equals(j2.Bitmap);
finally
j1.Free;
j2.Free;
end;
sw1.Stop;
end;
有什么方法可以直接访问文件中的像素数据字节(跳过元数据字节)而不进行位图转换?
【问题讨论】:
-
我会提取没有元数据的像素数据,并使用 md5-hashing 来比较内容。尝试一下可能是一个有用的想法...
-
@ChristopheD:知道如何直接提取像素数据吗?
-
一种蛮力的方法是查看图像的位图并使用扫描线循环。如果图像不同,它可能会很快停止......
-
@Dorin,最好的方法是比较标头后面的块,而不会像 MBo 试图解释的那样做出任何妥协(我不确定这是否像在所有情况下所说的那样简单,但是 @987654323 @例如是一个好看的非官方解释)。然后可能是
TJPEGImage.Bitmap的TGraphic.Equals,以防OP 想要直观地比较图像,将JPEG 解压缩为位图并将它们的像素与CompareMem进行比较。那是因为他们会是例如。用不同的方式压缩,但是...... -
@Dorin, ...视觉上肯定是一样的。这个问题是
TJPEGImage.Bitmapgetter 进行解压缩,除了几个步骤外,里面还有jpeg_read_scanlines,所以你可以尝试创建自己的函数,你可以在其中同时解压缩两个图像,一旦你会发现你已经完成并且有结果。我想指出这里的位图扫描线会解压缩两个图像并使用迭代,但TBitmap.Equals用于位图数据比较CompareMem并执行相同操作。
标签: delphi comparison jpeg