在windows mobile開發中,遇到一個問題,在.net compact framework框架下的Lockbits函數不能對圖像的部分像素進行鎖定,由於程序中必須用到該操作,因此試圖看能否解決這個問題,最後找到的解決方案就是藉助smart device framework類庫,只需要寥寥幾行代碼就可以實現這個功能,不錯,很好很強大。
之前已經介紹過了smart device framework的安裝,如果要使用它,只需要在項目中添加引用--》將需要的SDF的dll文件添加進來,同時在程序中開始部分添加對命名空間的引用,我這裏只用了OpenNETCF.dll和OpenNETCF.Drawing.dll兩個文件,因此只需要添加using OpenNETCF.Drawing和Using OpenNETCF.Drawing.Imaging、using OpenNETCF即可。
具體過程如下:
- 由於compact framework中不支持PixelFormat屬性,因此在Lockbits時參數PixelFormat必須指定爲一種,我這裏是設置爲常見的Format24bppRgb,即每個像素8位。
- 使用SDF的IBitmapImage類的Lockbits函數,它可以實現對圖像部分像素的鎖定。
int LockBits( RECT rect, //SDF中的矩形類,與MCF不同,它的初始化參數是左上角點座標和右下角點座標,而不是左上角座標和寬和高 uint flags, //用於指定圖像被鎖定的模式,只讀,可寫還是讀寫 PixelFormat pixelFormat, //指定圖像格式 ref BitmapDataInternal lockedBitmapData //返回被鎖定的內容,它包括我們需要的scan0屬性和Stride屬性 )
- 返回鎖定的內容,需要用到SDF中的BitmapDataInternal類,但是它是一個ref引用類也就是說必須在使用前賦值,參看它的構造函數得知,它需要一個BitmapData類(MCF中的)來對其初始化。
- 使用MCF中的Bitmap的Lockbits方法對圖像全部鎖定,得到一個BitmapData對象,使用它來初始化SDF的BitmapDataInternal對象。
- 接下來就可以使用IBitmapImage的Lockbits函數來鎖定圖像的部分像素,返回值就是引用的對象lockedBitmapData,使用它可以獲得鎖定內容的Scan0和Stride等屬性,就可以對圖像的部分像素進行下一步處理了。
- 別忘了要釋放UnlockBits(BitmapData)和UnlockBits(lockedBitmapData)
// convert the pixel format of the bitmap to something that we can handle
PixelFormat pf = CheckSupportedPixelFormat(PixelFormat.Format24bppRgb);IBitmapImage iBitmap;
BitmapDataInternal bmData;int xMax, yMax;
//----------------------------------------------
Rectangle fullImageSize = new Rectangle(0, 0, bmp.Width, bmp.Height);
System.Drawing.Imaging.BitmapData netBmData = bmp.LockBits(fullImageSize, System.Drawing.Imaging.ImageLockMode.ReadOnly, PixelFormat.Format24bppRgb);bmData = new BitmapDataInternal(netBmData);
ImagingFactory imgfactory = new ImagingFactory();imgfactory.CreateBitmapFromBuffer(ref bmData, out iBitmap);
RECT HorizeImageSize = new RECT(start, 0, end, bmp.Height);
RECT VerticalImageSize = new RECT(0, start, bmp.Width, end);if (direction == ScanDirection.Horizontal)
{
//NCF下Lockbits不支持部分鎖定
//bmData = bmp.LockBits(new Rectangle(start, 0, end - start, bmp.Height), ImageLockMode.ReadOnly, pf);//第一步:將NCF標準bitmap類轉換爲NCF下的IBitmapImage類
iBitmap.LockBits(HorizeImageSize, (uint)System.Drawing.Imaging.ImageLockMode.ReadOnly, PixelFormat.Format24bppRgb, ref bmData);
xMax = bmData.Height;
yMax = end - start;
}
else
{//bmData = bmp.LockBits(new Rectangle(0, start, bmp.Width, end - start), ImageLockMode.ReadOnly, pf);
iBitmap.LockBits(VerticalImageSize, (uint)System.Drawing.Imaging.ImageLockMode.ReadOnly, PixelFormat.Format24bppRgb, ref bmData);
xMax = bmp.Width;
yMax = bmData.Height;
}// Create the return value
byte[] histResult = new byte[xMax + 2]; // add 2 to simulate light-colored background pixels at sart and end of scanline
ushort[] vertSum = new ushort[xMax];unsafe
{
byte* p = (byte*)(void*)bmData.Scan0;
int stride = bmData.Stride; // stride is offset between horizontal lines in pfor (int y = 0; y < yMax; ++y)
{
// Add up all the pixel values vertically
for (int x = 0; x < xMax; ++x)
{
if (direction == ScanDirection.Horizontal)
vertSum[x] += getpixelbrightness(p, pf, stride, y, x);
else
vertSum[x] += getpixelbrightness(p, pf, stride, x, y);
}
}
}bmp.UnlockBits(netBmData);
iBitmap.UnlockBits(ref bmData);