首页 | 新闻资讯 | 软件应用 | 图形图像 | 网络应用 | 硬件学堂 | 程序开发 | 安全中心 | 素材下载 | 作者专区 | 学院论坛
精选专题 | 精美壁纸 | 专家答疑 | Flash剧场 | Photoshop | 名词解释 | 梦幻桌面 | PS高手进阶 | QQ区 | 图书 | 黑客教材
Flash教程| 卡通制作 | AutoCAD | 3DMax实例 | PS视频教程| 网页制作 | CorelDRAW| Firework | 滤镜与实例 | 全部视频教程
当前位置:eNet硅谷动力 > 学院频道 > VC#.NET

编程实例 使用C#的BitmapData
2008-03-05 08:46 来源:博客网
【简 介】
最近要转开发平台,正研究C#。C#好是好,不过处理图片时一个像素一个像素的操作像素不是一般的慢。
    
加入收藏  设为首页

最近要转开发平台,正研究C#。C#好是好,不过处理图片时一个像素一个像素的操作像素不是一般的慢。其实Delphi也一样,但好在Delphi的Bitmap类提供了ScanLines,可以一行一行的读图,效率比较高。C#应该也有类似的东东。经过一番搜索,终于发现了BitmapData类。

先看个例子,这是对一张位图的每个像素按FF取补,然后输出到一个新图(代码有点啰嗦,不过应该可以说明问题了)。

int h = m_Bmp.Height;
int w = m_Bmp.Width;

Bitmap bmpOut = new Bitmap(w, h, PixelFormat.Format24bppRgb);

BitmapData dataIn = m_Bmp.LockBits(new Rectangle(0,0,w,h),ImageLockMode.ReadOnly,PixelFormat.Format24bppRgb);
BitmapData dataOut = bmpOut.LockBits(new Rectangle(0, 0, w, h), ImageLockMode.ReadWrite, PixelFormat.Format24bppRgb);

unsafe
{
byte* pIn = (byte*)(dataIn.Scan0.ToPointer());
byte * pOut = (byte*)(dataOut.Scan0.ToPointer());

for (int y = 0; y < dataIn.Height; y++)
{
for (int x = 0; x < dataIn.Width; x++)
{

pOut[0] = (byte)(255 - pIn[0]);
pOut[1] = (byte)(255 - pIn[1]);
pOut[2] = (byte)(255 - pIn[2]);

pIn += 3;
pOut += 3;
}

pIn += dataIn.Stride - dataIn.Width * 3;
pOut += dataOut.Stride - dataOut.Width * 3;
}
}

bmpOut.UnlockBits(dataOut);
m_Bmp.UnlockBits(dataIn);


貌似比Delphi复杂得多,难道我真的天生对指针过敏?还是Delphi的比较好理解,就是扫描每一行,然后对当前像素点的三个分量做处理,非常方便。而且C#代码中的Stride是个什么东东?

查找了不少资料,现在我是这么理解的:

假设有一张图片宽度为6,因为是Format24bppRgb格式(每像素3字节。在以下的讨论中,除非特别说明,否则Bitmap都被认为是24位RGB)的,显然,每一行需要6*3=18个字节存储。对于Bitmap就是如此。但对于BitmapData,虽然BitmapData.Width还是等于Bitmap.Width,但大概是出于显示性能的考虑,每行的实际的字节数将变成大于等于它的那个离它最近的4的整倍数,此时的实际字节数就是Stride。就此例而言,18不是4的整倍数,而比18大的离18最近的4的倍数是20,所以这个BitmapData.Stride = 20。显然,当宽度本身就是4的倍数时,BitmapData.Stride = Bitmap.Width * 3。

画个图可能更好理解。R、G、B 分别代表3个原色分量字节,BGR就表示一个像素。为了看起来方便我在每个像素之间插了个空格,实际上是没有的。X表示补足4的倍数而自动插入的字节。为了符合人类的阅读习惯我分行了,其实在计算机内存中应该看成连续的一大段。

Scan0
 
 ---------Stride----------------- 
 ---------Width-------------    注:Width是图片(BGR作为一个单位)宽度
BGR BGR BGR BGR BGR BGR XX
BGR BGR BGR BGR BGR BGR XX
.
.
.

现在应该很好理解了。首先用 BitmapData.Scan0找到第0个像素的第0个分量的地址。这个地址指向的是个byte类型,所以当时定义为byte* pIn。
行扫描时,在当前指针位置(不妨看成当前像素的第0个颜色分量)连续取出三个值(3个原色分量。注意,0 1 2代表的次序是B G R。在取指针指向的值时,貌似p[n]和p += n再取p[0]是等价的),然后下移3个位置(pIn += 3,看成指到下一个像素的第0个颜色分量)。做过Bitmap.Width次操作后,就到达了Bitmap.Width * 3的位置,应该要跳过图中标记为X的字节了(共有Stride - Width * 3个字节),代码中就是 pIn += dataIn.Stride - dataIn.Width * 3;

跳过以后指针就到达下行的第0个像素了。按照此算法,一共需要做Bitmap.Height次行扫描(代码就是 for (int y = 0; y < dataIn.Height; y++))。

另外,因为使用了unsafe,所以编译的时候需要设置“允许不安全的代码”。
热门推荐 Win XP SP3 RC2官方下载及说明 U盘启动PE安装Win XP的成功经验


【责任编辑 彭凡】

关键字: 编程  技巧  C语言 
您对这篇文章的看法是:    喜欢 反感 支持 反对 加油 鄙视 学习 打击 佩服 漂亮 路过 发表评论
视频教程】 【专题汇总】 【不懂就问我关闭窗口

在逝去时光之国 Photoshop合成案例
Photoshop打造《女刺客》精彩插画
更新多多 奥运版MSN Shell亮点体验
熟悉各种交换机的数据接口类型
嬉皮时尚 Gucci Resort09女装设计
焦点文章
精品游戏
相关文章
 本栏目最新文章
·自学.NET之路-C#编程之基础总结
·数据结构(C#)_排序算法(冒泡排序)
·编程实例 使用C#的BitmapData
·C#实现窗口最小化到系统托盘
·C #中的几个线程同步对象方法
 精彩回放
·3DSMAX打造书本翻开效果
·共享上网技巧应用四则
·陪酒女浸泡在酒里的青春
·美女的性感靓丽婚纱设计
·妖冶身姿 死或生3壁纸
·剿灭Win XP下的29个烦恼
·黑客必备 NET命令大全
·用PS制作精致绝伦的红酒
 精彩推荐
 今日软件下载
·企业级即时通信平台 腾讯通RTX
·极品时刻表含春运临时列车数据
·下载管理器 BitComet 比特彗星
·边下边看想看就看风行网络电影
·超级图文影音转换器 Konvertor
 往日推荐
·手工破解网吧多种限制
·Windows 网络管理技巧
·WMP 10使用技巧三则
·女孩问你帅不帅 要小心
·注册表优化XP 20招
·制作XP万能ghost光盘
·WMP10火拼DVD播放器
·街头霸王图片集中营
·五大搜索引擎横向评测
·防御计算机病毒十大步骤

论坛精华
·eNet学院史上最优秀 
·家庭数码儿童照片的 
·PS做的静态的翻页效 
·PS初学者十三课,献给 
·photoshop插件集 
·使用 Photoshop 制作 
热点推荐
打造绚丽北极光
麻辣动态签名
Flash视频编程
章子怡月历桌面
热点关注
·网络安全Linux系统视频教程
·Autocad2007新手进阶之路
·Photoshop数码照片处理案例
·3DSMAX室内渲染实例视频教程
·鹏哥特色教程之C#入门到精通
·Flash AS3声音视频高级编程
·JAVA-J2ME移动开发实战教学
·Photoshop中文版完全解析
·瑞星卡卡上网助手 正版免费
用Illustrator打造蝴蝶飞舞效果
往日推荐
打造火焰文字
鹏哥C#教程
美女怀旧照片
3D室内渲染
焦点关注