C# BitmapData使用说明
msdn关于BitmapData原文解释地址:
http://msdn.microsoft.com/zh-cn/library/5ey6h79d(v=vs.110).aspx
以下是msdn原文给出的例子

private void LockUnlockBitsExample(PaintEventArgs e)
{ // Create a new bitmap.
Bitmap bmp = new Bitmap("c:\\fakePhoto.jpg"); // Lock the bitmap's bits.
Rectangle rect = new Rectangle(, , bmp.Width, bmp.Height);
System.Drawing.Imaging.BitmapData bmpData =
bmp.LockBits(rect, System.Drawing.Imaging.ImageLockMode.ReadWrite,
bmp.PixelFormat); // Get the address of the first line.
IntPtr ptr = bmpData.Scan0; // Declare an array to hold the bytes of the bitmap.
int bytes = Math.Abs(bmpData.Stride) * bmp.Height;
byte[] rgbValues = new byte[bytes]; // Copy the RGB values into the array.
System.Runtime.InteropServices.Marshal.Copy(ptr, rgbValues, , bytes); // Set every third value to 255. A 24bpp bitmap will look red.
for (int counter = ; counter < rgbValues.Length; counter += )
rgbValues[counter] = ; // Copy the RGB values back to the bitmap
System.Runtime.InteropServices.Marshal.Copy(rgbValues, , ptr, bytes); // Unlock the bits.
bmp.UnlockBits(bmpData); // Draw the modified image.
e.Graphics.DrawImage(bmp, , ); }

原文给出的例子已经可以理解出部分意思了,按照土鳖国王本人实验然后理解如下,如有误还请大神斧正
C#专门为图像处理提供了BitmapData,这个是真正的对位图的处理,首先将位图锁定到内存中,然后对位图的每一个像素进行处理,效率还是非常高的,下面先给出偶自己转化图像灰度值的例子,以函数的形式给出
以便需要的朋友直接可以使用,可以说是任何操作都是依次为基础的,如果觉得注释太多,可将注释直接删除,然后将代码烤白可直接使用,指针法效率更高,这里只给出内存法先理解,然后便可大展身手了,哈哈

/// 获取灰度值返回byte[]
/// <summary>
/// 获取灰度值返回byte[]
/// </summary>
/// <param name="srcBmp">源图像</param>
/// <param name="rect">要锁定的图像区域</param>
/// <returns>返回byte[]</returns>
public static byte[] GetGrayArray(Bitmap srcBmp, Rectangle rect)
{
//将Bitmap锁定到系统内存中
//rect是指源图像中需要锁定那一块矩形区域进行处理
//ImageLockMode.ReadWrite是指对图像出操作的权限,枚举有只读,只写,用户输入缓冲区,还是读写
//PixelFormat.Format24bppRgb
//参数确定了该图像信息时rgb存储还是Argb存储,如果是Format24ppRgb则处理的图像像素就是BGR方式存储,我们这里没有特别指出,均是Format24bppRgb方式存储处理
BitmapData srcBmpData = srcBmp.LockBits(rect, ImageLockMode.ReadWrite, PixelFormat.Format24bppRgb);
//位图中第一个像素数据的地址。它也可以看成是位图中的第一个扫描行
IntPtr srcPtr = srcBmpData.Scan0;
//将Bitmap对象的信息存放到byte数组中
//假设本图像的宽度和高度为5*3
/*
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 //这里存储为一维数组,所以是一行,
宽度为5,高度为3,则像素总数为15,这里要清楚,每一个像素是rgb三个值,故而,一维数组中
存储为
0 1 2 3 4 5 6 7 8 9 10 11 12 13 14
15...44
这里分行是为了便于理解,一维数组存储类似是一行,但是我们的图像的宽度是5也就是我们图像的第一行是0123...到14,下一行是15...29,下一行是30...44,高度为3,所以就是3行
012 345 678 91011 121314
bgr bgr bgr bgr bgr
151617 181920 ...
bgr bgr ...
这样存储
*/
//所以才有了这里的*3就是指一个像素是三个分量值
int scanWidth = rect.Width * ;
//而每行的实际的字节数将变成大于等于它的那个离它最近的4的整倍数,此时的实际字节数就是Stride,如果上面的第三个参数Format24ppRgb如果设置为Format32ppRgb,这个时候存储的时候就是4位存储一个像素,如果是Format32bppArgb同样也是4为存储一个像素,这4位除了bgr三个分量之外还有透明度A的值
//至于为什么是24,32,这是因为计算机存储数据为8bit存储1个字节,
//bgr3个就是3*8=24,4个就是4*8=32了,为什么是16,8位等,索引图等原理是一样的
//int srcStride = srcBmpData.Stride;
int src_bytes = scanWidth * rect.Height; //这里就是计算出了需要存储的像素所占用的空间大小
byte[] srcValues = new byte[src_bytes]; //定义源图像的元信息
byte[] grayValues = new byte[rect.Width * rect.Height]; //定义转化为灰度后需要存储的数组
//复制GRB信息到byte数组,将从srcPtr开始的第一个扫描行开始扫描信息,然后读取到srcValues数组中
Marshal.Copy(srcPtr, srcValues, , src_bytes);
//解锁位图
srcBmp.UnlockBits(srcBmpData); //读取完元信息,这里就不用了,一定要记得解锁,否则会报错
//下面就是你想怎么处理都成了,,灰度化,转换空间模式,除噪声,腐蚀,膨胀,反色,二值化等等均可
//灰度化处理
int m = , j = ;
int k = ;
byte gray;
//根据重要性及其它指标,将三个分量以不同的权值进行加权平均。由于人眼对绿色的敏感最高,对蓝色敏感最低,因此,按下式对RGB三分量进行加权平均能得到较合理的灰度图像
//根据Y = 0.299*R + 0.587*G + 0.114*B //加权平均法
for (int i = ; i < rect.Height; i++)
{
for (j = ; j < rect.Width; j++)
{
//注意位图结构中RGB按BGR的顺序存储
k = * j;
gray = (byte)(srcValues[i * scanWidth + k + ] * 0.299
+ srcValues[i * scanWidth + k + ] * 0.587
+ srcValues[i * scanWidth + k + ] * 0.114);
grayValues[m] = gray; //将灰度值存到double的数组中
m++;
}
}
return grayValues;
} //接下来就很简单了,下面在给出获得到灰度值存储为2位数组的方法,按照习惯二维处理起来比较好理解
/// 获取灰度值存到二维double数组中,这个是将rgb转化为灰度值
/// <summary>
/// 获取灰度值存到二维double数组中,这个是将rgb转化为灰度值
/// </summary>
/// <param name="srcBmp"></param>
/// <returns>2Dimension</returns>
public static byte[,] GetGrayArray2D(Bitmap srcBmp,Rectangle rect)
{
int width = rect.Width;
int height = rect.Height; BitmapData srcBmpData = srcBmp.LockBits(rect, ImageLockMode.ReadWrite, PixelFormat.Format24bppRgb); IntPtr srcPtr = srcBmpData.Scan0; int scanWidth = width * ;
int src_bytes = scanWidth * height;
//int srcStride = srcBmpData.Stride;
byte[] srcRGBValues = new byte[src_bytes];
byte[,] grayValues = new byte[height, width];
//RGB[] rgb = new RGB[srcBmp.Width * rows];
//复制GRB信息到byte数组
Marshal.Copy(srcPtr, srcRGBValues, , src_bytes);
//解锁位图
srcBmp.UnlockBits(srcBmpData);
//灰度化处理
int m = , i = , j = ; //m表示行,j表示列
int k = ;
byte gray; for (i = ; i < height; i++) //只获取图片的rows行像素值
{
for (j = ; j < width; j++)
{
//只处理每行中图像像素数据,舍弃未用空间
//注意位图结构中RGB按BGR的顺序存储
k = * j;
gray = (byte)(srcRGBValues[i * scanWidth + k + ] * 0.299
+ srcRGBValues[i * scanWidth + k + ] * 0.587
+ srcRGBValues[i * scanWidth + k + ] * 0.114); grayValues[m, j] = gray; //将灰度值存到double的数组中
}
m++;
} return grayValues;
} //此方法是直接得到灰度图
/// 获取灰度图像,将制定图片转化为灰度图
/// <summary>
/// 获取灰度图像,将制定图片转化为灰度图
/// </summary>
/// <param name="srcBmp"></param>
/// <returns></returns>
public static Bitmap GetGrayImage(Bitmap srcBmp)
{
Rectangle rect = new Rectangle(, , srcBmp.Width, srcBmp.Height);
BitmapData srcBmpData = srcBmp.LockBits(rect, ImageLockMode.ReadWrite, PixelFormat.Format24bppRgb);
IntPtr srcPtr = srcBmpData.Scan0;
int scanWidth = srcBmpData.Width * ;
int src_bytes = scanWidth * srcBmp.Height;
byte[] srcRGBValues = new byte[src_bytes];
Marshal.Copy(srcPtr, srcRGBValues, , src_bytes);
//灰度化处理
int k = ;
for (int i = ; i < srcBmp.Height; i++)
{
for (int j = ; j < srcBmp.Width; j++)
{
k = j * ;
//0.299*R + 0.587*G + 0.144*B = 亮度或灰度
//只处理每行中图像像素数据,舍弃未用空间
//注意位图结构中RGB按BGR的顺序存储
byte intensity = (byte)(srcRGBValues[i * scanWidth + k + ] * 0.299
+ srcRGBValues[i * scanWidth + k + ] * 0.587
+ srcRGBValues[i * scanWidth + k + ] * 0.114);
srcRGBValues[i * scanWidth + k + ] = intensity;
srcRGBValues[i * scanWidth + k + ] = intensity;
srcRGBValues[i * scanWidth + k + ] = intensity;
}
}
Marshal.Copy(srcRGBValues, , srcPtr, src_bytes);
//解锁位图
srcBmp.UnlockBits(srcBmpData);
return srcBmp;
}

以上就是C# BitmapData的使用介绍,首先融会贯通,其次举一反三,方可熟能生巧

C# BitmapData使用说明的更多相关文章

  1. jQuery Webcam Plugin jscam.swf文件反编译工具使用说明

    jQuery webcam plugin是一个在ie,firefox,chrome下都可以用的摄像头摄像及拍照用的插件. (http://www.xarg.org/project/jquery-web ...

  2. Atitit.项目修改补丁打包工具 使用说明

    Atitit.项目修改补丁打包工具 使用说明 1.1. 打包工具已经在群里面.打包工具.bat1 1.2. 使用方法:放在项目主目录下,执行即可1 1.3. 打包工具的原理以及要打包的项目列表1 1. ...

  3. awk使用说明

    原文地址:http://www.cnblogs.com/verrion/p/awk_usage.html Awk使用说明 运维必须掌握的三剑客工具:grep(文件内容过滤器),sed(数据流处理器), ...

  4. “我爱背单词”beta版发布与使用说明

    我爱背单词BETA版本发布 第二轮迭代终于画上圆满句号,我们的“我爱背单词”beta版本已经发布. Beta版本说明 项目名称 我爱背单词 版本 Beta版 团队名称 北京航空航天大学计算机学院  拒 ...

  5. Oracle 中 union 和union all 的简单使用说明

    1.刚刚工作不久,经常接触oracle,但是对oracle很多东西都不是很熟.今天我们来了解一下union和union all的简单使用说明.Union(union all): 指令的目的是将两个 S ...

  6. Map工具系列-02-数据迁移工具使用说明

    所有cs端工具集成了一个工具面板 -打开(IE) Map工具系列-01-Map代码生成工具说明 Map工具系列-02-数据迁移工具使用说明 Map工具系列-03-代码生成BySQl工具使用说明 Map ...

  7. Map工具系列-03-代码生成BySQl工具使用说明

    所有cs端工具集成了一个工具面板 -打开(IE) Map工具系列-01-Map代码生成工具说明 Map工具系列-02-数据迁移工具使用说明 Map工具系列-03-代码生成BySQl工具使用说明 Map ...

  8. jQuery验证控件jquery.validate.js使用说明

    官网地址:http://bassistance.de/jquery-plugins/jquery-plugin-validation jQuery plugin: Validation 使用说明 转载 ...

  9. gdbsever 使用说明

    gdbsever 使用说明 在新塘N3292x平台下 编译 gdbsever ./configure --target=arm-linux --host=arm-linux arm-linux-gdb ...

随机推荐

  1. J2SE核心开发实战(二)——字符串与包装类

    字符串与包装类 一.实验简单介绍 在本章.我们将学习一些用于处理字符串的API以及包装类的相关知识. 本章知识点 字符串API 包装类及其应用 二.认识字符串类 1. 什么是字符串类 Java字符串类 ...

  2. Activity左边滑出,右边滑入的动画切换

    Activity左边滑出,右边滑入的动画切换 转载请注明出处:http://blog.csdn.net/u012301841/article/details/46920809 大家都知道Android ...

  3. 5. TCP客户/服务器程序示例

    signal 信号是一种软件中断,异步发生,在进程运行的时候随时可能发生.信号可以: 由一个进程发给另一个进程,或发给自身 由内核发给某个进程 信号的action: signal handler,在信 ...

  4. mysql 查询正在执行的事务以及等待锁 常用的sql语句

    使用navicat测试学习: 首先使用set autocommit = 0;(取消自动提交,则当执行语句commit或者rollback执行提交事务或者回滚)   在打开一个执行update查询 正在 ...

  5. Java获取域名

    private static final char URL_SPLASH = '/'; private static final String URL_SCHEME_POSTFIX = ": ...

  6. (转)CSS3全局实现所有元素的内边距和边框不增加

    全局设置 border-box 很好,首先它符合直觉,其次它可以省去一次又一次的加加减减 它还有一个关键作用——让有边框的盒子正常使用百分比宽度.但是使用了 border-box 可能会与一些依赖默认 ...

  7. eclipse通过maven建立java se工程配置log4j,打包成zip,将jar包和配置文件分开,并以bat和sh文件启动java程序

    一.新建maven的java工程 1.eclipse里file-new-other,选择maven Project 2.选中 Use default Workspace location,然后 nex ...

  8. bash shell中的特殊用法

    1 ${BASH_SOURCE-$0} 表示当前正在执行的脚本的完整路径. 2 cd -P 以物理路径进入 /usr/localhadoop现在链到/home/houzhizhen/usr/local ...

  9. 在安卓6.0(及以上)设备上无法获取无线网卡MAC地址的解决方案

    在安卓6.0以下的设备上,通过WifiManager.getConnectionInfo().getMacAddress()即可获取WLAN物理地址, 而在6.0及以上,以此方式获取到的MAC地址为固 ...

  10. 使用libcurl的包装库cpr发起http请求

    cpr GitHub地址https://github.com/whoshuu/cpr 简单示例:cpr_http_request.cpp #include <iostream> #incl ...