blueyi's notes

Follow Excellence,Success will chase you!

0%

图像处理相关总结及.NET的BitmapData类

关于位图图像的深度

这里只涉及位图图像
  首先图像总像素个数=宽 * 高,每个像素的颜色深浅信息是通过图像的位深度来决定的。所以位深度也直接影响着一个图像占用的总字节数,常见的图像多数都是位图。
  位深度的解释:在记录数字图像的颜色时,计算机实际上是用每个像素需要的位深度来表示的。黑白二色的图像是数字图像中最简单的一种,它只有黑、白两种颜色,也就是说它的 每个像素只有1位颜色,位深度是1,用2的一次幂来表示;考虑到位深度平均分给R, G, B和Alpha,而只有RGB可以相互组合成颜色。所以4位颜色的图,它的位深度是4,只有2的4次幂种颜色,即16种颜色或16种灰度等级 ) 。8位颜色的图,位深度就是8,用2的8次幂表示,它含有256种颜色 ( 或256种灰度等级 )。24位颜色可称之为真彩色,位深度是24,它能组合成2的24次幂种颜色,即:16777216种颜色 ( 或称千万种颜色 ),超过了人眼能够分辨的颜色数量。当我们用24位来记录颜色时,实际上是以2^(8×3),即红、绿、蓝 ( RGB ) 三基色各以2的8次幂,256种颜色而存在的,三色组合就形成一千六百万种颜色。

注意1个字节8位
所以常见图像中的位深与像素的关系可以理解为:
24位深:一个像素占24/8=3个字节,通常的彩色图片是24位深
8位深:一个像素占8/8=1个字节,灰度图
1位深:一个像素占1/8个字节,二值图

关于图像宽度和图像扫描宽度

  此处以.NET Framework下的BitmapData类来解释,关于BitmapData类的详细信息看官网https://msdn.microsoft.com/zh-cn/library/system.drawing.imaging.bitmapdata%28v=vs.110%29.aspx
  在BitmapData类中图像宽度即为Bitmap.Width,图像扫描宽度是BitmapData.Stride。
  首先需要知道使用BitmapData类对图像进行操作时的扫描行宽度并不是图像宽度,而是等于离图像宽度最近的4的整数倍,也就是这个数字必须是4的倍数,所以在计算实际处理的字节数时也必须使用扫描宽度,即Stride。当然如果图像宽度刚好是4的倍数,那么此时BitmapData.Stride = Bitmap.Width。具体为什么要这样处理,有人说是考虑性能问题。
假设有一张宽度为6的位图,其格式为Format24bppRgb,即24位深,从上面可以知道,它一个像素占3个字节。那么每一行需要6*3=18字节存储,由于在BitmapData中Stride必须是离宽度最近的4的整数倍且,所以Stride应该为20,在内存中可以理解为:

1
2
3
4
5
6
-----|------- Stride -------|
-----|------- Width------|
Scan0:
-----BGR BGR BGR BGR BGR BGR XX
-----BGR BGR BGR BGR BGR BGR XX
-----BGR BGR BGR BGR BGR BGR XX

常用到的计算:
在使用BitmapData类对图像扫描时,整个图像的存储所占的字节数即为扫描宽度乘以图像高度,即BitmapData.Stride x Bitmap.height,它们都是int类型。
扫描间隙即一行中未使用的字节 = 扫描宽度 - 图像宽度 * (位深 / 8) = (4 - (图像宽度 * (位深 / 8) % 4)
扫描宽度=图像宽度 * 一个像素所占的字节数 + (4 - (图像宽度*(位深/8)%4)

Welcome to my other publishing channels