C#编程之处理图像格式协议说明
白羽 2018-07-10 来源 :网络 阅读 1247 评论 0

摘要:本文将带你了解C#编程之处理图像格式协议说明,希望本文对大家学C#/.Net有所帮助。




       许多图像处理任务即时是最简单的文件类型转换,例如从32位深度到8位深度的格式转化,直接获得像素阵列要比使用GetPixel和SetPixel等方法的效率高得多。

       你可能会发现DotNet采用托管机制,大多数情况下微软会推荐你使用托管代码,理由是便捷和安全。实际应用中,直接操作内存中的数据块是很少见的,尽管如此,图像处理恰恰是这类为数不多的情况之一,因为使用托管代码的效率低的难以忍受,特别是对巨幅图像来说,在此,我们讨论一下一种新的方法。

       如何使用非托管代码是因语言而异的,在C#中我们可以通过unsafe关键字来调用指针,从而直接操作内存中的位图数据;VB则使用Marshal类中的方法,它会导致一部分的性能损失,因此效率不如前者。

 

锁定比特流

     Bitmap类使用LockBits和UnLockBits方法来将位图的数据矩阵保存在内存中、直接对它进行操作,最后用修改后的数据代替位图中的原始数据。LockBits返回以各BitmapData的类用已描述数据在已锁定的矩阵中的位置和分布。

      BitmapData类包括以下几个重要的属性:

Scan0:数据矩阵在内存中的地址。

Stride:数据矩阵中的行宽,以byte为单位。可能会扩展几个Byte,后面会介绍。

PixelFormat:像素格式,这对矩阵中字节的定位很重要。

Width:位图的宽度。

Height:位图的高度。

C#编程之处理图像格式协议说明


 

       如上图所示,stride属性表示位图数据矩阵的行宽,以byte为单位。出于效率考虑,矩阵的行宽并非刚好是每行像素数的整数倍,系统往往会将其封装成4的整数倍。举例来说,对于一幅24位深17像素宽的图像,其stride属性为52;每行的数据量为17*3=51,系统将其自动封装一个字节,所以它的stride为52byte(或13*4byte)。对于一幅17像素宽的4位索引图,其stride为12,其中9byte(准确地说是8.5个byte)用来记录数据信息,每行再自动添加3(3.5)个byte保证其为4的整数倍。

      具体数据的分布因其pixel format而异。24位深的图像每隔3个byte包含一组RGB信息;32位深的图像每隔4个byte包含一组RGBA信息。那些每个字节包含多个像素的pixel format,比如4位索引图像或1位索引图像,必须经过仔细处理,从而保证同一字节中的相邻byte不会混淆。

指针的准确定位

32位RGB:假设X、Y为位图中像素的坐标,则其在内存中的地址为scan0+Y*stride+X*4。此时指针指向蓝色,其后分别是绿色、红色,alpha分量。

24位RGB:scan0+Y*stride+X*3。此时指针指向蓝色,其后分别是绿色和红色。

8位索引:scan0+Y*stride+X。当前指针指向图像的调色盘。

4位索引:scan0+Y*stride+(X/2)。当前指针所指的字节包括两个像素,通过高位和低位索引16色调色盘,其中高位表示左边的像素,低位表示右边的像素。

1位索引:scan0+Y*stride+X/8。当前指针所指的字节中的每一位都表示一个像素的索引颜色,调色盘为两色,最左边的像素为8,最右边的像素为0。

像素间使用迭代器

    下面这个范例将一幅32位深的图像中所有像素的蓝色分量设为最大(255):

    BitmapData bmd=bm.LockBits(new Rectangle(0, 0, 10, 10),    System.Drawing.Imaging.ImageLockMode.ReadOnly, bm.PixelFormat);

     int PixelSize=4;

     for(int y=0; y<bmd.Height; y++)

     {

        byte* row=(byte *)bmd.Scan0+(y*bmd.Stride);

        for(int x=0; x<bmd.Width; x++)

        {

          row[x*PixelSize]=255;

        }

     }

      处理4位索引图,高低位应分开处理,代码如下:

 

    int offset = (y * bmd.Stride) + (x >> 1);

      byte currentByte = ((byte *)bmd.Scan0)[offset];

      if((x&1) == 1)

      {

        currentByte &= 0xF0;

        currentByte |= (byte)(colorIndex & 0x0F);

      }

      else

      {

        currentByte &= 0x0F;

        currentByte |= (byte)(colorIndex << 4);

      }

      ((byte *)bmd.Scan0)[offset]=currentByte;

 

      处理1位索引的代码:

 

byte* p=(byte*)bmd.Scan0.ToPointer();

      int index=y*bmd.Stride+(x>>3);

      byte mask=(byte)(0x80>>(x&0x7));

      if(pixel)

        p[index]|=mask;

      else

        p[index]&=(byte)(mask^0xff);

 

      最后在进行完所有处理后马不要忘记使用Unlockbits命令解锁。

 


以上就介绍了C#.NET的相关知识,希望对C#.NET有兴趣的朋友有所帮助。了解更多内容,请关注职坐标编程语言C#.NET频道!


本文由 @白羽 发布于职坐标。未经许可,禁止转载。
喜欢 | 0 不喜欢 | 0
看完这篇文章有何感觉?已经有0人表态,0%的人喜欢 快给朋友分享吧~
评论(0)
后参与评论

您输入的评论内容中包含违禁敏感词

我知道了

助您圆梦职场 匹配合适岗位
验证码手机号,获得海同独家IT培训资料
选择就业方向:
人工智能物联网
大数据开发/分析
人工智能Python
Java全栈开发
WEB前端+H5

请输入正确的手机号码

请输入正确的验证码

获取验证码

您今天的短信下发次数太多了,明天再试试吧!

提交

我们会在第一时间安排职业规划师联系您!

您也可以联系我们的职业规划师咨询:

小职老师的微信号:z_zhizuobiao
小职老师的微信号:z_zhizuobiao

版权所有 职坐标-一站式IT培训就业服务领导者 沪ICP备13042190号-4
上海海同信息科技有限公司 Copyright ©2015 www.zhizuobiao.com,All Rights Reserved.
 沪公网安备 31011502005948号    

©2015 www.zhizuobiao.com All Rights Reserved

208小时内训课程