在德尔福检查图像

时间:2010-03-11 11:40:39

标签: delphi

我正在尝试对图像进行校验,但是给出结果需要太长时间,尝试添加值和Adler-32但是两者都会在很长一段时间内完成(大约2秒)。

添加值:

Function Checksum_CountryFlag(Img : TPicture):Integer;
var j, k, Checksum : Integer;
begin
Checksum := 0;
For j := 0 to Img.Width do
For k := 0 to Img.Height do
If (((Img.Bitmap.Canvas.Pixels[j,k]) <> 15577344) And ((Img.Bitmap.Canvas.Pixels[j,k]) <> 15311104) And ((Img.Bitmap.Canvas.Pixels[j,k]) <> 3816255) And ((Img.Bitmap.Canvas.Pixels[j,k]) <> 10526623) And ((Img.Bitmap.Canvas.Pixels[j,k]) <> 12303034) And ((Img.Bitmap.Canvas.Pixels[j,k]) <> 9013641)) Then
begin
Checksum := Checksum + Img.Bitmap.Canvas.Pixels[j,k];
end;
Result := Abs(Checksum);
end;

阿德勒-32:

Function Checksum_Adler32(Img : TPicture):Integer;
var i,a,b,j,k : Integer;
begin
a := 1; b := 0;
For j := 0 to Img.Width do
For k := 0 to Img.Height do
If (((Img.Bitmap.Canvas.Pixels[j,k]) <> 15577344) And ((Img.Bitmap.Canvas.Pixels[j,k]) <> 15311104) And ((Img.Bitmap.Canvas.Pixels[j,k]) <> 3816255) And ((Img.Bitmap.Canvas.Pixels[j,k]) <> 10526623) And ((Img.Bitmap.Canvas.Pixels[j,k]) <> 12303034) And ((Img.Bitmap.Canvas.Pixels[j,k]) <> 9013641)) Then
begin
a := a + Img.Bitmap.Canvas.Pixels[j,k];
b := b + a;
end;
Result := Abs(a) + Abs(b);
end;

如你所见,我试图避免一些价值观(技术原因)。 也许这就是需要太长时间,我不知道,还有什么改进这个算法的想法?

4 个答案:

答案 0 :(得分:6)

我做了一些修正,以快速制作代码的第一个版本:

Function Checksum_CountryFlag(Img : TPicture):Integer;
var j, k, Checksum : Integer;
  Line: PLongInt;
begin
  Checksum := 0;
  Img.Bitmap.PixelFormat:= pf32bit; // just for case
  For k := 0 to Img.Height - 1 do begin      //  !! Height first, -1
    Line:= Img.Bitmap.ScanLine[k];
    For j := 0 to Img.Width - 1 do begin  // !! -1
      If ((Line^ <> 15577344) And (Line^ <> 15311104) And (Line^ <> 3816255)
        And (Line^ <> 10526623) And (Line^ <> 12303034) And (Line^ <> 9013641)) Then
        begin
          Checksum := Checksum + Line^;
        end;
      Inc(Line);
    end;
  end;
  Result := Abs(Checksum);
end;

更新:它提供了不同的结果,因为我修复了代码中的错误(Height-1),(Width-1)。我也改变了循环顺序(外部循环的高度) - 使用ScanLine是必要的。在比较之前,您必须在代码中执行相同的更正。

答案 1 :(得分:2)

展开你的循环部分可以提供更多的性能(将img.bitmap.canvas放入循环外的变量中)。
在if之前将像素[j,k]变为局部变量也有助于改善,并且提高了源代码的可读性。

但最大的影响可能是使用“Scanline”属性并将一行中的所有像素变为局部变量有助于更多(您必须切换循环的高度和宽度)。

答案 2 :(得分:2)

很难确定没有分析器,但是看着我猜你会失去很多时间反复查找Img.Bitmap.Canvas.Pixels[j,k]的读者值。

我要做的第一件事就是把它保存到一个值,如下:

pixel := Img.Bitmap.Canvas.Pixels[j,k];
If ((pixel <> 15577344) And (pixel <> 15311104) And (pixel <> 3816255) And (pixel <> 10526623) And (pixel <> 12303034) And (pixel <> 9013641)) Then

这应该会显着加快速度。

答案 3 :(得分:2)

Serg'代码具有更正(和更快)的像素值:

Function Checksum_CountryFlag(Img : TPicture):Integer;
var j, k, Checksum : Integer;
  Line: PIntegerArray;
  Pixel : integer;
begin
  Checksum := 0;
  Img.Bitmap.PixelFormat:= pf32bit; // just for case
  For k := 0 to Img.Height - 1 do begin      //  !! Height first, -1
    Line:= Img.Bitmap.ScanLine[k];
    For j := 0 to Img.Width - 1 do begin  // !! -1
      Pixel := Line^[j];
      If ((Pixel <> 15577344) And (Pixel <> 15311104) And (Pixel <> 3816255)
        And (Pixel <> 10526623) And (Pixel <> 12303034) And (Pixel <> 9013641)) Then
        begin
          Checksum := Checksum + Pixel;
        end;
      Inc(Line);
    end;
  end;
  Result := Abs(Checksum);
end;