日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

LockBits in GDI+【转】http://timothyqiu.com/archives/lockbits-in-gdiplus/

發布時間:2025/7/14 编程问答 43 豆豆
生活随笔 收集整理的這篇文章主要介紹了 LockBits in GDI+【转】http://timothyqiu.com/archives/lockbits-in-gdiplus/ 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

LockBits in GDI+

發布時間:March 31, 2011?分類:技術

什么東西一旦追求起效率來最終還是要歸到比較底層的操作,比如 GDI 中直接操作位圖數據就要用?GetDIBits?/?SetDIBits(或者已經廢棄的?GetBitmapBits?/?SetBitmapBits)。因為最近要處理的都是?GDI 處理不了的 PNG 格式圖片,所以還是用上了 GDI+。GDI+ 中直接操作?Bitmap?的數據就要用?LockBits?/?UnlockBits?了。

第一眼看見?Bitmap::LockBits?的聲明我就比較暈:

Status LockBits(const Rect *rect,UINT flags,PixelFormat format,BitmapData *lockedBitmapData );

不過說實話,整個 GDI+ 庫的風格相對于 M$ 的其它庫來說已經是很清新脫俗了 :)

rect
要鎖定的矩形區域,一般都是鎖定整個圖像大小。(吐槽:為神馬不能傳?NULL?進去表示全圖啊~)
flags
鎖定區域要進行讀操作還是寫操作,以及是否自己分配緩沖區。(看著比較不順眼的?UINT?類型可取的值其實是?enum)
format
鎖定區域所需的像素格式,如果和圖片本身的格式不符,GDI+ 會自動進行轉換。
lockedBitmapData
輸出鎖定區域信息,成員變量?Scan0?會指向被鎖定的像素區域(如果?flags?里指定自己分配緩沖區的話,系統只是往?Scan0?所指緩沖區寫數據)。

那么鎖定全圖進行讀操作就是:

int w = bmp->GetWidth(); int h = bmp->GetHeight(); BitmapData bmpData; bmp->LockBits(Rect(0, 0, w, h), ImageLockModeRead, PixelFormat32bppARGB, &bmpData);

鎖定完圖像區域,就可以對得到的?BitmapData?進行操作了。BitmapData?包含了被鎖定區域的長、寬、格式、指針信息。取坐標 (x, y) 的像素顏色可以用:

unsigned int *pData = reinterpret_cast<unsigned int *>(bmpData.Scan0); int stride = bmpData.Stride; unsigned int color = pData[y * stride / 4 + x]; // color= 0xAARRGGBB

有一個比較特別的?Stride?成員,它表示「一行」圖像對應的緩沖區所實際占用的字節數(因為位圖文件有一條變態的規則:圖片數據在存儲時每一行字節數必須是 4 的倍數,如果真實圖片數據寬度不是 4 的倍數則需要用垃圾數據補齊不足的字節數,于是就造成了?Stride?≠?Width?的現象,即所謂的字節對齊)。

對于圖片數據操作完以后要記得對鎖定區域進行解鎖:

bmp->UnlockBits(&bmpData);

這樣一來就功德圓滿了。

嗯~這段筆記就是這樣,這真是有意義的一天啊~

自己提供緩沖區

咳咳~距剛剛寫這篇東西已經有大半年了,在仔細看 GDI+ 的文檔時又發現了些有用的東東。

正如你所看到的,上邊所說的「LockBits?→ 讀寫?bmpData.San0?→?UnlockBits」的三部曲其實并不與 GDI 中的?GetDIBits?/?SetDIBits?完全對應。至少后者是直接從位圖中讀取數據到我們自己提供的顏色緩沖區、直接從自己的顏色緩沖區寫到位圖中去,而前者卻需要在 Lock 后一行一行、甚至一個像素一個像素地手動交換。

好消息是?Bitmap::LockBits?的?flags?參數除了可以傳入?ImageLockModeRead?和?ImageLockModeWrite?外還可以同時或上一個?ImageLockModeUserInputBuf。這個標志位表示讓?LockBits?使用我們傳入的?BitmapData?中的緩沖區信息來進行讀寫,而不是由它來分配、我們來讀寫。

舉個栗子 :)

int w = bmp->GetWidth(); int h = bmp->GetHeight(); unsigned int *buffer = new unsigned int[w * h * 4]; // 緩沖區,以 32 位色 ARGB 模式讀取 BitmapData bmpData; bmpData.Width = w; bmpData.Height = h; bmpData.Stride = w * 4; // 緩沖區每行大小,自行分配,每行就沒有多余字節了 bmpData.Scan0 = buffer; bmpData.PixelFormat = PixelFormat32bppARGB; bmpData.Reserved = NULL; bmp->LockBits(Rect(0, 0, w, h),ImageLockModeRead | ImageLockModeUserInputBuf,PixelFormat32bppARGB,&bmpData); bmp->UnlockBits(&bmpData);

轉載于:https://www.cnblogs.com/songtzu/archive/2013/01/25/2876805.html

總結

以上是生活随笔為你收集整理的LockBits in GDI+【转】http://timothyqiu.com/archives/lockbits-in-gdiplus/的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。