全國最多中醫師線上諮詢網站-台灣中醫網
發文 回覆 瀏覽次數:2646
推到 Plurk!
推到 Facebook!

以 Lazarus 實作取代 TBitmap.ScanLine 處理方式

 
digitraveler
初階會員


發表:89
回覆:91
積分:46
註冊:2005-06-01

發送簡訊給我
#1 引用回覆 回覆 發表時間:2010-03-13 22:08:53 IP:61.221.xxx.xxx 訂閱
ScanLine 是 TBitmap 元件中的一個 Property, 存放著 Bitmap 某一橫列的色彩值在記憶體中存放的起始指標, 有了這個指標, 我們就可以直接在記憶體中直接存取, 修改影像內容; 很多高速影像轉換處理都會用到這個屬性, 可是在 Lazarus 中的 TBitmap 並不支援這個屬性, 原因是這個屬性有高度的裝置依賴性, 不適合跨平台上使用

Developing with Graphics
http://wiki.freepascal.org/Developing_with_Graphics
中有說明
The first thing to remember is that Lazarus is meant to be platform independent, so any methods using Windows API functionality are out of the question. So a method like ScanLine is not supported by Lazarus because it is intended for Device Independant Bitmap and uses functions from the GDI32.dll.

其中也有舉了 FadeIn() (即影像的 "淡入" 處理) 分別以 Delphi 及 Lazarus 程式碼撰寫的例子; 當然, Delphi 例子是透過 TBitmap.ScanLine 處理, 效率會比較好(影像處理速度較快)

但我個人覺得 Developing with Graphics 網頁中這兩個 FadeIn() 例子舉的很爛, 好像是不同兩個人寫的, 區域變數命名也差很多, 對照兩相程式碼很難抓到差異重點, 所以我把它改了一下成為下面兩個例子, 是否更容易用來做差異比較呢 ?



[code delphi]
■ Delphi 版本 FadeIn()

procedure TForm1.FadeIn(aBitMap: TBitMap);
var
Bitmap1, Bitmap2: TBitmap;
Row1, Row2: PRGBTripleArray;
px, py, FadeStep: integer;
CurColor: TColor;
begin
Bitmap1 := TBitmap.Create;
Bitmap1.PixelFormat := pf32bit; // or pf24bit
Bitmap1.Assign(aBitMap);

Bitmap2 := TBitmap.Create;
Bitmap2.PixelFormat := pf32bit;
Bitmap2.Assign(aBitMap);

//With Scanline
for FadeStep := 0 to 32 do begin
for py := 0 to (Bitmap1.Height - 1) do begin
Row1 := Bitmap1.Scanline[py];
Row2 := Bitmap2.Scanline[py];
for px := 0 to (Bitmap1.Width - 1) do begin
Row2[px].rgbtRed := (FadeStep * Row1[px].rgbtRed) shr 5;
Row2[px].rgbtGreen := (FadeStep * Row1[px].rgbtGreen) shr 5; // Fading
Row2[px].rgbtBlue := (FadeStep * Row1[px].rgbtBlue) shr 5;
end;
end;
Form1.Canvas.Draw(0, 0, Bitmap2);
InvalidateRect(Form1.Handle, nil, False);
RedrawWindow(Form1.Handle, nil, 0, RDW_UPDATENOW);
end;


Bitmap1.Free;
Bitmap2.Free;

end;



■ Lazarus 版本 FadeIn()

procedure TForm1.FadeIn(aBitMap: TBitMap);
var
IntfImg1, IntfImg2: TLazIntfImage;
ImgHandle,ImgMaskHandle: HBitmap;
FadeStep: Integer;
px, py: Integer;
CurColor: TFPColor;
TempBitmap: TBitmap;
Row1, Row2: PRGBTripleArray;
begin
IntfImg1:=TLazIntfImage.Create(0,0);
IntfImg1.LoadFromBitmap(aBitmap.Handle,aBitmap.MaskHandle);
IntfImg2:=TLazIntfImage.Create(0,0);
IntfImg2.LoadFromBitmap(aBitmap.Handle,aBitmap.MaskHandle);

//Without Scanline
for FadeStep:=1 to 32 do begin
for py:=0 to IntfImg1.Height-1 do begin
for px:=0 to IntfImg1.Width-1 do begin
CurColor:=IntfImg1.Colors[px,py];
CurColor.Red:=(CurColor.Red*FadeStep) shr 5;
CurColor.Green:=(CurColor.Green*FadeStep) shr 5;
CurColor.Blue:=(CurColor.Blue*FadeStep) shr 5;
IntfImg2.Colors[px,py]:=CurColor;
end;
end;
IntfImg2.CreateBitmaps(ImgHandle,ImgMaskHandle,false);
TempBitmap:=TBitmap.Create;
TempBitmap.Handle:=ImgHandle;
TempBitmap.MaskHandle:=ImgMaskHandle;
Canvas.Draw(0,0,TempBitmap);
end;

IntfImg1.Free;
IntfImg2.Free;
TempBitmap.Free;
end;

[/code]



-------------------------------------------------------------------------

■ Lazarus 版本取代 TBitmap.ScanLine 處理方式 (讓 Lazarus 也能高效率處理圖型)

參考了上兩個我改寫的例子後, 馬上發現差異點就是 : Delphi 全程以 TBitMap 處理圖型, 而 Lazarus 是先把 TBitMap 轉成 TLazIntfImage 再做處理, 在先前搜尋資料時有印象 TLazIntfImage 有類似 TBitmap.ScanLine 的屬性
也就是 TLazIntfImage.GetDataLineStart, 也是透過指標方式高速處理的方式, 所以再把上面兩個例子綜合一下, 就成了 Lazarus With Scanline 高速處理圖型版本, 經過實測的確有 Delphi TBitmap.ScanLine 的處理速度, 而且透過TLazIntfImage 物件的這種寫法是跨平台的 (較低的裝置依賴性)


[code delphi]
type
PRGBTripleArray = ^TRGBTripleArray;
TRGBTripleArray = array[0..32767] of TRGBTriple;

procedure TForm1.FadeIn2(aBitMap: TBitMap);
var
IntfImg1, IntfImg2: TLazIntfImage;
ImgHandle,ImgMaskHandle: HBitmap;
FadeStep: Integer;
px, py: Integer;
CurColor: TFPColor;
TempBitmap: TBitmap;
Row1, Row2: PRGBTripleArray;
begin
IntfImg1:=TLazIntfImage.Create(0,0);
IntfImg1.LoadFromBitmap(aBitmap.Handle,aBitmap.MaskHandle);

IntfImg2:=TLazIntfImage.Create(0,0);
IntfImg2.LoadFromBitmap(aBitmap.Handle,aBitmap.MaskHandle);


//With Scanline
for FadeStep:=1 to 32 do begin
for py:=0 to IntfImg1.Height-1 do begin
Row1 := IntfImg1.GetDataLineStart(py); //like Delphi TBitMap.ScanLine
Row2 := IntfImg2.GetDataLineStart(py); //like Delphi TBitMap.ScanLine
for px:=0 to IntfImg1.Width-1 do begin
Row2^[px].rgbtRed:= (FadeStep * Row1^[px].rgbtRed) shr 5;
Row2^[px].rgbtGreen := (FadeStep * Row1^[px].rgbtGreen) shr 5; // Fading
Row2^[px].rgbtBlue := (FadeStep * Row1^[px].rgbtBlue) shr 5;
end;
end;
IntfImg2.CreateBitmaps(ImgHandle,ImgMaskHandle,false);

TempBitmap:=TBitmap.Create;
TempBitmap.Handle:=ImgHandle;
TempBitmap.MaskHandle:=ImgMaskHandle;
Canvas.Draw(0,0,TempBitmap);
end;


IntfImg1.Free;
IntfImg2.Free;
TempBitmap.Free;
end;


[/code]


■ 相關參考
http://tw.myblog.yahoo.com/bruce0829/



■ 程式下載 (含 source code)
http://digitraveler.homelinux.com/down_load/LazScanLineTest.zip



編輯記錄
digitraveler 重新編輯於 2010-03-15 06:32:46, 註解 無‧
digitraveler 重新編輯於 2010-03-15 06:33:32, 註解 無‧
digitraveler 重新編輯於 2010-03-15 06:38:00, 註解 無‧
digitraveler 重新編輯於 2010-03-15 06:39:01, 註解 無‧
digitraveler 重新編輯於 2010-03-15 06:41:40, 註解 無‧
taishyang
站務副站長


發表:377
回覆:5490
積分:4563
註冊:2002-10-08

發送簡訊給我
#2 引用回覆 回覆 發表時間:2010-03-15 09:54:30 IP:122.116.xxx.xxx 訂閱
感謝分享 ^_^
ANDY8C
資深會員


發表:114
回覆:582
積分:299
註冊:2006-10-29

發送簡訊給我
#3 引用回覆 回覆 發表時間:2010-03-16 18:35:12 IP:210.66.xxx.xxx 訂閱
我是才開始想用 Lazarus 的,對 Lazarus 所知不多....
但您的深入分析,感覺很實用....也許某天會用上
謝謝您


------
---------------------------------------
偶爾才來 KTOP ,交流條碼問題,在 FB [條碼標籤達人] 社團留言,感恩.
系統時間:2024-04-29 14:30:37
聯絡我們 | Delphi K.Top討論版
本站聲明
1. 本論壇為無營利行為之開放平台,所有文章都是由網友自行張貼,如牽涉到法律糾紛一切與本站無關。
2. 假如網友發表之內容涉及侵權,而損及您的利益,請立即通知版主刪除。
3. 請勿批評中華民國元首及政府或批評各政黨,是藍是綠本站無權干涉,但這裡不是政治性論壇!