为了获得更快的处理速度.我采用直接对内存的访问.现在有几点不明之处:
public static bool Gray(Bitmap b)
{
BitmapData bmData = b.LockBits(new Rectangle(0, 0, b.Width, b.Height),
ImageLockMode.ReadWrite, PixelFormat.Format24bppRgb);
int stride = bmData.Stride;
System.IntPtr Scan0 = bmData.Scan0;
unsafe
{
byte * p = (byte *)(void *)Scan0;
int nOffset = stride - b.Width*3;
byte red, green, blue;
for(int y=0;y <b.Height ;y++) {
for(int x=0; x < b.Width; ++x )
{
blue = p[0];
green = p[1];
red = p[2];
p[0] = p[1] = p[2] = (byte)(.299 * red + .587 * green + .114 * blue);
p += 3;
}
p += nOffset;
}
}
b.UnlockBits(bmData);
return true;
} 以上这段是我的网上copy的代码. Bitmap bt1 = new Bitmap(this._Picture1.Image);
BitmapData bd = bt1.LockBits(new Rectangle(0, 0, bt1.Width, bt1.Height), ImageLockMode.ReadWrite,Format.Format24bppRgb);
System.IntPtr PIni = bd.Scan0; //开始地址
int Stride = bd.Stride; //扫描宽度
unsafe
{
byte* p = (byte*)PIni.ToPointer(); //指针指向开始地址 ........................
p = p+3;
}此段代码是我自己写的.问题1: byte * p = (byte *)(void *)Scan0; 与 byte* p = (byte*)PIni.ToPointer(); 这样有什么不同.
问题2: p += nOffset; 为什么要加这个偏移量. 我没有加好象也没有错. 他加了也没有错.为什么会这样.
public static bool Gray(Bitmap b)
{
BitmapData bmData = b.LockBits(new Rectangle(0, 0, b.Width, b.Height),
ImageLockMode.ReadWrite, PixelFormat.Format24bppRgb);
int stride = bmData.Stride;
System.IntPtr Scan0 = bmData.Scan0;
unsafe
{
byte * p = (byte *)(void *)Scan0;
int nOffset = stride - b.Width*3;
byte red, green, blue;
for(int y=0;y <b.Height ;y++) {
for(int x=0; x < b.Width; ++x )
{
blue = p[0];
green = p[1];
red = p[2];
p[0] = p[1] = p[2] = (byte)(.299 * red + .587 * green + .114 * blue);
p += 3;
}
p += nOffset;
}
}
b.UnlockBits(bmData);
return true;
} 以上这段是我的网上copy的代码. Bitmap bt1 = new Bitmap(this._Picture1.Image);
BitmapData bd = bt1.LockBits(new Rectangle(0, 0, bt1.Width, bt1.Height), ImageLockMode.ReadWrite,Format.Format24bppRgb);
System.IntPtr PIni = bd.Scan0; //开始地址
int Stride = bd.Stride; //扫描宽度
unsafe
{
byte* p = (byte*)PIni.ToPointer(); //指针指向开始地址 ........................
p = p+3;
}此段代码是我自己写的.问题1: byte * p = (byte *)(void *)Scan0; 与 byte* p = (byte*)PIni.ToPointer(); 这样有什么不同.
问题2: p += nOffset; 为什么要加这个偏移量. 我没有加好象也没有错. 他加了也没有错.为什么会这样.
解决方案 »
- htmlEditor 源码里的图片地址问题
- 你能给我修改下,我需要只显示“名字或平均成绩”,名字不需要重复,求助····
- FtpWebRequest支持linux的FTP服务器吗?
- 望高手推荐几本c# GDI+的好书!(推荐即给分,谢谢!)
- 多线程群发邮件,老是有重复(跟定义的线程数一样多),跪求大家帮忙分析分析!
- 谁帮我看看怎么会抛出异常来。。。已经搞晕了,咬牙切齿去睡觉了
- 如何软件换肤?
- c# 很棘手的问题估计碰到过的人很多 求救
- 我是新手,急盼有人教我怎么做。
- C#中的中文问题
- 存储过程分页调用问题(求解)
- 如何将两个dataset比较的结果,插入到另一个dataset中,并绑定到一个指定的GRID上
问题二,nOffset 是偏移量,但就像LZ说的不加也没错,不知道为什么不错,但加上也没错,
人家都加了,所以还是加上了
假设有一张图片宽度为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---------| |
BGR BGR BGR BGR BGR BGR XX
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;