四、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;
以上代碼不完整,可以根據需要進行修改。