原文:图像处理中的跨度(stride)

使用C#的BitmapData

最近要转开发平台,正研究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,所以编译的时候需要设置“允许不安全的代码”。

Posted: 2006年12月27日 14:22 作者 biojaye

图像处理中的跨度(stride)相关推荐

  1. 图像处理中的Mask是什么

    图像处理中的Mask是什么 1.什么是掩膜 数字图像处理中的掩膜的概念是借鉴于PCB制版的过程,在半导体制造中,许多芯片工艺步骤采用光刻技术,用于这些步骤的图形"底片"称为掩膜(也 ...

  2. 图像处理中消除相机透镜畸变和视角变换

    from:图像处理中消除相机透镜畸变和视角变换 一般的针孔相机模型如下: 三维坐标点经过透视投影变换,转换到一个图像平面坐标点. 而相机透镜还存在一定的畸变,包括横向畸变和切向畸变. 因此,针孔相机模 ...

  3. 图像处理中常用数学知识

    2.3.3 赋范空间 每个实数或复数,都有相对应的绝对值或者模,每一个n维矢量,也都可以定义其长度.如果把"长度"的概念推广到一般抽象空间中的元素上,就可以得到范数这个概念. 本节 ...

  4. 图像处理中的拉普拉斯算子

    图像处理中的拉普拉斯算子 (2010-03-10 20:44:14) 转载▼ 标签: 算子 拉普拉斯变换 灰度 图像 杂谈 分类:图像处理 1.基本理论 拉普拉斯算子是最简单的各向同性微分算子,具有旋 ...

  5. jsp中两个double相乘_图像处理中的代数运算及几何变换

    图像运算是图像处理中常用的处理方法,它以图像为单位进行操作,运算的结果是一副新的图像,常常用于图像的高级处理(如图像分割,目标的检测和识别等)的前期处理.具体的图像运算包括点运算,代数运算,几何运算和 ...

  6. 图像处理中的通信原理——冈萨雷斯读书笔记(三)

    法国数学家傅里叶男爵在1822年出版的<热分析理论>一书中指出,任何周期函数都可以表示为不同频率的正弦和或余弦和(每个正弦项/余弦项乘不同的系数)的形式,这其实就是无穷级数的一种:傅里叶级 ...

  7. 图像处理中的通信原理——冈萨雷斯读书笔记(一)

    信息的概念在信息论中很明确:用于衡量事件的不确定性.信息的传播形式或者所载体便是信号,比如说电信号.光信号.声音信号.那么信息的表现形式就是消息,可以是语言.文字.图像.所以说图像处理依然是信息与通信 ...

  8. 图像处理中的卷积与模板

    图像处理中的卷积与模板 1.使用模板处理图像相关概念:       模板:矩阵方块,其数学含义是一种卷积运算. 卷积运算:可看作是加权求和的过程,使用到的图像区域中的每个像素分别与卷积核(权矩阵)的每 ...

  9. 图像处理中各种边缘检测的微分算子简单比较(Sobel,Robert, Prewitt,Laplacian,Canny)

    图像处理中各种边缘检测的微分算子简单比较(Sobel,Robert, Prewitt,Laplacian,Canny) 不同图像灰度不同,边界处一般会有明显边缘,利用此特征可以分割图像.需要说明的是: ...

最新文章

  1. Mycat 安装配置
  2. 机器学习股票_使用概率机器学习来改善您的股票交易
  3. 拼接大屏数据展示_可视化大屏的UI设计是根据哪几个方面来进行?
  4. rfid技术及应用答案王佳斌_详解工业数据采集中RFID技术的应用
  5. Servlet3.0 多图片,文件上传
  6. mapreduce实现矩阵相乘
  7. c语言贪吃蛇(简易版本含完整代码)
  8. Fiddler下载视频号中的视频最简教程
  9. Java开发实用的面试题及参考答案
  10. 自举电容充电回路分析
  11. The client-side rendered virtual DOM tree is not matching server-rendered content.
  12. AV1编码器优化技术
  13. ahocorasick使用
  14. JAVA的远程控制系统(远程监控)实现
  15. java word 添加水印图片_Java添加Word文本水印和图片水印
  16. win10 WSL kali 下载源 --另外 恭喜马哥喜提博客
  17. 电视服务器绑上电池信号强吗,路由器上面绑电池,可以增加WiFi信号,真的有作用吗?...
  18. 呵,无趣——自我反省
  19. 鲁班,视觉生成引擎的应用
  20. 2022年中国一体化压铸行业概览:*引领潮流,*或成资本新宠

热门文章

  1. 计算字符串相似度算法—Levenshtein
  2. php 时间 插件,PHP中Carbon日期时间处理利器详解
  3. NPashaP的二分图源码部分
  4. HDU 4256 翻译罗马数字
  5. MariaDB 主从同步与热备(14)
  6. CentOS-6.4无线上网命令行配置
  7. SQL 交集 差集 并集 笛卡尔积 应用实例
  8. [原]android2.3如何使用SharedPreferences存储字符串集合类型的元素
  9. 使用ExtJs创建新的UI控件(转)
  10. 快速清除SQL Server数据库日志的方法