Delphi下实现全屏快速找图找色 四、BitmapData.pas的使用

四、BitmapData.pas的使用

(注:以上压缩包中的BitmapData.pas文件有个小BGU,主要是截取鼠标指针的图片时没有考虑当前的背景颜色,始终为黑色。在本贴三楼的压缩包中有更新后的BitmapData.pas文件下载。)

  在上面的压缩包中是BitmapData.pas使用的示范程序,BitmapData.pas文件可以从压缩包中获得。在BitmapData.pas文件中我将位图数据封装成了类TBDBitmapData,以便于使用。另外我编写一系列的函数用以BGR格式颜色的构建、转换、模糊比较。注意在BitmapData.pas文件中我定义了一些常量,这些常量只是为了增加程序的可读性,修改这些常量不会修改程序支持数据的格式,只会使程序运行错误。BitmapData.pas文件的详细说明如下:

1、function BGR(B,G,R : Byte): TBDColor;

  根据蓝(B)、绿(G)、红(R)三个通道的值生成一个BGR格式颜色。

2、function RGBtoBGR(C : TColor): TBDColor;

  将一个RGB颜色格式转换到BGR颜色格式。

3、function BGRtoRGB(C : TBDColor): TColor;

  将一个BGR颜色格式转换到RGB颜色格式。

4、function BDCompareColor(C1,C2 : TBDColor; const Range : TBDColorRange): Boolean;

  根据颜色范围Range比较颜色C1和C2,返回C1和C2是否相似。C1和C2是BGR格式的颜色,Range是颜色的变化范围。

TBDColorRange的定义如下:

TBDColorRange = record

R: Integer;

G: Integer;

B: Integer;

end;

  其中,R表示C1和C2中红色通道最大的相差值;G表示C1和C2中绿色通道最大的相差值;B表示C1和C2中蓝色通道最大的相差值。

  示范程序,比较两个颜色:

var

C1,C2 : TBDColor;

Range : TBDColorRange;

begin

Range.R:=5;

Range.G:=5;

Range.B:=5;

C1:=BGR(125,125,125);

C2:=BGR(120,120,120);

BDCompareColor(C1,C2,Range); //成功

C1:=BGR(125,120,125);

C2:=BGR(120,120,120);

BDCompareColor(C1,C2,Range); //成功

C1:=BGR(125,200,125);

C2:=BGR(120,120,120);

BDCompareColor(C1,C2,Range); //失败

end;

5、constructor TBDBitmapData.Create(const AName : String);

  新建一个TBDBitmapData对象的实例。可以为实例指定一个名字,便于以后的管理。

6、procedure TBDBitmapData.Clear;

  清除当前TBDBitmapData对象中加载的位图数据。

7、function TBDBitmapData.LoadFromStream(Stream : TStream; ABackColor : TBDColor): Boolean;

  从数据流Stream中导入位图数据,返回是否成功。如果失败将设置Error成员说明情况。数据流中的数据必需是24位BMP格式文件数据。利用ABackColor可以设定图片的背景颜色,该参数可以省略,省略时表示图片不使用背景颜色。

8、function TBDBitmapData.SaveToStream(Stream : TStream):Boolean;

  将当前加载的位图数据导出到数据流Stream中,返回是否成功。如果失败将设置Error成员说明情况。数据将按24位BMP文件数据格式导出到数据流中。

9、function TBDBitmapData.LoadFromFile(const FileName : string; ABackColor : TBDColor): Boolean;

  从文件FileName中导入位图数据,返回是否成功。如果失败将设置Error成员说明情况。文件必需是24位BMP格式文件。利用ABackColor可以设定图片的背景颜色,该参数可以省略,省略时表示图片不使用背景颜色。

10、function TBDBitmapData.SaveToFile(const FileName : string): Boolean;

  将当前加载的位图数据导出到文件中,返回是否成功。如果失败将设置Error成员说明情况。数据按24位BMP文件数据格式导出到文件中。

11、function TBDBitmapData.LoadFromBitmap(Bitmap : TBitmap): Boolean;

  从一个TBitmap对象中导入数据,返回是否成功。如果失败将设置Error成员说明情况。导入时图片的背景颜色由Bitmap.Transparent和Bitmap.TransparentColor决定。

12、function TBDBitmapData.SaveToBitmap(Bitmap : TBitmap): Boolean;

  将当前的位图数据导出到一个TBitmap对象中,返回是否成功。如果失败将设置Error成员说明情况。导出时将根据当前的背景颜色设置Bitmap.Transparent和Bitmap.TransparentColor成员。利用LoadFromBitmap和SaveToBitmap两个函数可以实现TBDBitmapData对象和TBitmap对象的相互转换。

13、function TBDBitmapData.CopyFormScreen(Left,Top,AWidth,AHeight : Integer): Boolean;

  从屏幕上的指定范围中截图,并导入数据,返回是否成功。如果失败将设置Error成员说明情况。Left为截图的左边距,可省略,默认为0;Top为截图的顶边距,可省略,默认为0;AWidth为截图的宽度,可省略,默认为从Left到屏幕右边的宽度;AHeight为截图的高度,可省略,默认为从Top到屏幕底边的高度。

14、function TBDBitmapData.CopyFormCursor: Boolean;

  截取鼠标当前指针的图片,并导入数据,返回是否成功。如果失败将设置Error成员说明情况。如果鼠标指针是动画指针,默认截取第一帧画面。截取时会使用当前背景颜色填充背景,如果没有指定背景颜色则使用白色(RGB(255,255,255))填充。

15、function TBDBitmapData.Compare(Bmp : TBDBitmapData; Left,Top : Integer): Boolean;

16、function TBDBitmapData.Compare(Bmp : TBDBitmapData; const Range : TBDColorRange; Left,Top : Integer): Boolean;

  重载的两个函数,用于在当前位图的指定位置比较Bmp指定的位图,返回是否一致。无论比较是否一致都不会修改Error成员。第一个函数用于精确比较,第二个函数用于模糊比较。Bmp指定的位图面幅要小于等于当前位图的面幅,Bmp指定的位图不能超出当前位图,否则比较失败。Bmp为指定的位图数据;Left为比较时的左边距,可省略,默认为0;Top为比较时的顶边距,可省略,默认为0;Range为颜色变化范围。

17、function TBDBitmapData.FindImage(Bmp : TBDBitmapData; var Left,Top : Integer): Boolean;

18、function TBDBitmapData.FindImage(Bmp : TBDBitmapData; const Range : TBDColorRange; var Left,Top : Integer): Boolean;

  重载的两个函数,从当前位图中查找与Bmp一致的子图,返回是否找到。无论是否找到都不会修改Error成员。第一个函数用于精确比较,第二个函数用于模糊比较。查找时忽略Left和Top的设置,从当前位图的左上角开始按从左到右,从上到下的顺序查找。找到返回true,设置Left和Top为找到子图的位置;没找到返回false,设置Left和Top为-1。Bmp为指定的子图数据;Left为找到子图的左边距;Top为找到子图的顶边距;Range为颜色变化范围。

  示范程序,在屏幕上查找子图:

var

Bit1,Bit2 : TBDBitmapData;

Left,Top : Integer;

begin

Bit1:=TBDBitmapData.Create;

Bit2:=TBDBitmapData.Create;

Bit1.CopyFormScreen;

Bit2.LoadFromFile('文件名');

if Bit1.FindImage(Bit2,Left,Top) then

begin

{已找到子图,进行相应的处理...}

end;

Bit1.Free;

Bit2.Free;

end;

19、function TBDBitmapData.FindCenterImage(Bmp : TBDBitmapData; var Left,Top : Integer): Boolean;

20、function TBDBitmapData.FindCenterImage(Bmp : TBDBitmapData; const Range : TBDColorRange; var Left,Top : Integer): Boolean;

  重载的两个函数,从当前位图中查找与Bmp一致的子图,返回是否找到。无论是否找到都不会修改Error成员。第一个函数用于精确比较,第二个函数用于模糊比较。查找时以Left和Top的设置为基点,从中心向四周查找。找到返回true,设置Left和Top为找到子图的位置;没找到返回false,设置Left和Top为-1。Bmp为指定的子图数据;Left为找到子图的左边距;Top为找到子图的顶边距;Range为颜色变化范围。

21、function TBDBitmapData.EnumImage(Bmp : TBDBitmapData; EnumImageProc : TBDEnumImageProc; lParam : Integer): Boolean;

22、function TBDBitmapData.EnumImage(Bmp : TBDBitmapData; const Range : TBDColorRange; EnumImageProc : TBDEnumImageProc; lParam : Integer): Boolean;

  重载的两个函数,从当前位图中查找所有与Bmp一致的子图,即枚举位图,返回是否找到。无论是否找到都不会修改Error成员。第一个函数用于精确比较,第二个函数用于模糊比较。查找时从当前位图的左上角开始按从左到右,从上到下的顺序查找。每当查找到一个子图,就调用回调函数EnumImageProc,如果EnumImageProc返回false就停止查找,结束函数。Bmp为子图数据;EnumImageProc为回调函数;lParam为调用回调函数时发出的参数,可省略,默认为0;Range为颜色变化范围。TBDEnumImageProc的声明格式如下:

TBDEnumImageProc = function (Left,Top : Integer; Bmp : TBDBitmapData; lParam : Integer): Boolean;

  其中,Left为找到子图的左边距;Top为找到子图的顶边距;Bmp为调用EnumImage时给出的查找子图数据;lParam为调用EnumImage时给出的设置参数。该函数的返回值表示是否继续枚举。

23、function TBDBitmapData.FindColor(Color : TBDColor; var Left,Top : Integer): Boolean;

24、function TBDBitmapData.FindColor(Color : TBDColor; const Range : TBDColorRange; var Left,Top :Integer): Boolean;

  重载的两个函数,从当前位图中查找指定的颜色,忽略当前位图背景颜色BackColor的设置,返回是否找到。无论是否找到都不会修改Error成员。第一个函数用于精确比较,第二个函数用于模糊比较。查找时忽略Left和Top的设置,从当前位图的左上角开始按从左到右,从上到下的顺序查找。找到返回true,设置Left和Top为找到颜色的位置,没找到返回false,设置Left和Top为-1。Color为BGR格式颜色;Left为找到颜色的左边距;Top为找到颜色的顶边距;Range为颜色变化范围。

25、function TBDBitmapData.FindCenterColor(Color : TBDColor; var Left,Top : Integer): Boolean;

26、function TBDBitmapData.FindCenterColor(Color : TBDColor; const Range : TBDColorRange; var Left,Top : Integer): Boolean;

  重载的两个函数,从当前位图中查找指定的颜色,忽略当前位图背景颜色BackColor的设置,返回是否找到。无论是否找到都不会修改Error成员。第一个函数用于精确比较,第二个函数用于模糊比较。查找时以Left和Top的设置为基点,从中心向四周查找。找到返回true,设置Left和Top为找到颜色的位置,没找到返回false,设置Left和Top为-1。Color为BGR格式颜色;Left为找到颜色的左边距;Top为找到颜色的顶边距;Range为颜色变化范围。

  示范程序,在屏幕上以某点为中心向四周模糊查找颜色:

var

Bit : TBDBitmapData;

Range : TBDColorRange;

Left,Top : Integer;

begin

Bit:=TBDBitmapData.Create;

Bit.CopyFormScreen;

Range.R:=5;

Range.G:=5;

Range.B:=5;

Left:=600;

Top:=380;

if Bit.FindCenterColor(BGR(0,250,250),Range,Left,Top) then

begin

{已找到颜色,进行相应的处理...}

end;

Bit.Free;

end;

27、function TBDBitmapData.EnumColor(Color : TBDColor; EnumColorProc : TBDEnumColorProc; lParam : Integer): Boolean;

28、function TBDBitmapData.EnumColor(Color : TBDColor; const Range : TBDColorRange; EnumColorProc : TBDEnumColorProc; lParam : Integer): Boolean;

  重载的两个函数,从当前图片中查找所有指定的颜色,即枚举颜色,忽略当前位图背景颜色BackColor的设置,返回是否找到。无论是否找到都不会修改Error成员。第一个函数用于精确比较,第二个函数用于模糊比较。查找时从当前位图的左上角开始按从左到右,从上到下的顺序查找。每找到一个颜色,就调用回调函数EnumColorProc,如果EnumColorProc返回false就停止查找,结束函数。Color为BGR格式颜色;EnumColorProc为回调函数;lParam为调用回调函数时发出的参数,可省略,默认为0;Range为颜色变化范围。TBDEnumColorProc的声明格式如下:

TBDEnumColorProc = function (Left,Top : Integer; Color : TBDColor; lParam : Integer): Boolean;

  其中,Left为找到颜色的左边距;Top为找到颜色的顶边距;Color为找到的颜色,当使用模糊查找时该颜色为实际找到的颜色;lParam为调用EnumColor时给出的设置参数。该函数的返回值表示是否继续枚举。

29、TBDBitmapData.Error

  最近一次操作出现的错误的说明。出于性能方面的考虑,只有导入、导出、截图等操作才会修改这个成员。而查找、枚举等操作无论是否成功都不会修改这个成员。

30、TBDBitmapData.Name

  当前位图的名称,可读写。方便位图数据的管理。

31、TBDBitmapData.Width

  当前位图宽度,以象素为单位,只读。

32、TBDBitmapData.Height

  当前位图高度,以象素为单位,只读。

33、TBDBitmapData.BackColor

  当前位图的背景颜色,BGR格式的颜色,可读写。当该颜色为BD_COLORLESS时,表示该位图不使用背景颜色。

34、TBDBitmapData.LineWidth

  对齐后每行位图数据的宽度,以字节为单位,只读。

35、TBDBitmapData.SpareWidth

  对齐后每行位图数据填充的多余宽度,以字节为单位,只读。

36、TBDBitmapData.Size

  位图数据的长度,以字节为单位,只读。

37、TBDBitmapData.Bits

  位图数据缓冲区指针,只读。这个指针是只读的,但它指向的数据是可读写的。可以将这个属性看成是一个一维的字节数组,可以对缓冲区中的数据进行访问和修改。

38、TBDBitmapData.Pixels[Left,Top : Integer]

  位图的象素颜色,BGR格式的颜色,可读写。利用这个属性可以将位图看成是一个二维的象素矩阵,可以对矩阵中的象素颜色进行访问和修改。

  示范代码,位图数据的访问:

var

Bit : TBDBitmapData;

begin

Bit:=TBDBitmapData.Create;

Bit.CopyFormScreen;

Bit.Bits[50]; //以Byte格式访问

Bit.Pixels[10,10]; //以BGR颜色格式访问

Bit[10,10]; //等同于Bit.Pixels[10,10];

Bit.Free;

end;

利用TBDBitmapData对象查找两张图片上的不同,从右上角开始利用双层循环遍历两图上的所有象素点,并相互比较。不完整代码如下:

procedure TForm1.Button5Click(Sender: TObject);

var

Bmp1,Bmp2 : TBDBitmapData;

Left,Top : Integer;

IsExit : Boolean;

begin

Bmp1:=TBDBitmapData.Create;

Bmp2:=TBDBitmapData.Create;

Bmp1.LoadFromFile('文件名1');

Bmp2.LoadFromFile('文件名2');

//假设两张图片一样大

IsExit:=false;

for Top:=0 to Bmp1.Height-1 do

begin

for Left:=0 to Bmp1.Width-1 do

begin

if Bmp1[Left,Top]<>Bmp2[Left,Top] then

begin

//在(Left,Top)位置两张图片有不同

//相应的处理...

if {如果不继续查找其它不同} then

begin

IsExit:=true; //用以退出循环

break;

end;

end;

end;

if IsExit then break;

end;

Bmp1.Free;

Bmp2.Free;

end;

以上代码不完整,可以根据需要进行修改。