在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);