以 Lazarus 實作取代 TBitmap.ScanLine 處理方式 |
|
digitraveler
初階會員 發表:89 回覆:91 積分:46 註冊:2005-06-01 發送簡訊給我 |
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 發送簡訊給我 |
|
ANDY8C
資深會員 發表:114 回覆:582 積分:299 註冊:2006-10-29 發送簡訊給我 |
本站聲明 |
1. 本論壇為無營利行為之開放平台,所有文章都是由網友自行張貼,如牽涉到法律糾紛一切與本站無關。 2. 假如網友發表之內容涉及侵權,而損及您的利益,請立即通知版主刪除。 3. 請勿批評中華民國元首及政府或批評各政黨,是藍是綠本站無權干涉,但這裡不是政治性論壇! |