浅谈.NET图片快速处理的几种方法
创始人
2024-04-21 20:01:26
0

这里首先要介绍一个类System.Drawing.Imaging.BitmapData,直接实例化这个类没有用处,我们需要将一个Bitmap锁定到内存中,来获取一个BitmapData的实例。.NET图片快速处理方法如下:

使用Bitmap.LockBits(Rectangle rect, ImageLockMode flags, PixelFormat format)或者它的另一个重载Bitmap.LockBits(Rectangle rect, ImageLockMode flags, PixelFormat format, BitmapData bitmapData)来将图像数据锁定到内存中,以此来获取一个与指定图片相关联的BitmapData实例。

在BitmapData中有一个重要的属性Scan0,它是一个指针,指向了图片数据所在内存的***个位置。使用内存跟踪,将Scan0的值填入地址中,可以看到内存的分配情况(Format32bppArgb颜色深度):

内存的分配情况

这些值与图片像素的对应关系是这样的:

值与图片像素的对应关系


现在我们可以使用System.Runtime.InteropServices.Marshal.WriteByte(IntPtr ptr, byte val)的方法来更改指定位置的像素值了,修改后只要再调用一次Bitmap.UnlockBits(BitmapData bitmapdata)来解锁内存就可以了,例如:

  1. private void LockUnlockBitsExample(PaintEventArgs e)  
  2. {  
  3. Bitmap bmp = new Bitmap("c:\\fakePhoto.jpg");  
  4. Rectangle rect = new Rectangle(0, 0, bmp.Width, bmp.Height);  
  5. System.Drawing.Imaging.BitmapData bmpbmpData =  
  6. bmp.LockBits(rect, System.Drawing.Imaging.ImageLockMode.ReadWrite,  
  7. bmp.PixelFormat);  
  8. IntPtr ptr = bmpData.Scan0;  
  9. int bytes = bmp.Width * bmp.Height * 3;  
  10. byte[] rgbValues = new byte[bytes];  
  11. for (int counter = 0; counter < rgbValues.Length; counter += 3)  
  12. {  
  13. Marshal.WriteByte(ptr, counter, 255);  
  14. }  
  15. bmp.UnlockBits(bmpData);  
  16. e.Graphics.DrawImage(bmp, 0, 0);  

此.NET图片快速处理示例将图片上所有像素的Red向量设置为255。运行此实例可以看到图片变色了。

每次调用System.Runtime.InteropServices.Marshal.WriteByte(IntPtr ptr, byte val)的方法并不方便,因此我们构造一个ColorBgra类用来储存这4个颜色向量,它的主要代码是这样的(参考自Paint.Net提供的源码):

  1. [StructLayout(LayoutKind.Explicit)]  
  2. public struct ColorBgra  
  3. {  
  4. [FieldOffset(0)]  
  5. public byte B;  
  6.    
  7. [FieldOffset(1)]  
  8. public byte G;  
  9.    
  10. [FieldOffset(2)]  
  11. public byte R;  
  12.    
  13. [FieldOffset(3)]  
  14. public byte A;  
  15.  
  16. ///  
  17. /// Lets you change B, G, R, and A at the same time.  
  18. /// 
  19.  
  20. [FieldOffset(0)]  
  21. public uint Bgra;  
  22. public override string ToString()  
  23. {  
  24. return "B: " + B + ", G: " + G + ", R: " + R + ", A: " + A;  
  25. }  

使用这个类在声明为unsafe的上下文中就可以通过计算偏移量的办法寻址找到指定位置像素的地址(指针),例如在Format32bppArgb颜色深度的图片中可以这样计算:

  1. public unsafe ColorBgra* GetPointAddress(int x, int y)  
  2. {  
  3. return y * 4 + x;  

将计算返回的指针赋给ColorBgra*。之后使用如下方法:

  1. color->B = i;  color ->G = i;  color ->R = i;  color ->A = i;  

直接把值写入内存中,实现.NET图片快速处理操作。

【编辑推荐】

  1. .NET 4.0内存映射文件详解
  2. .NET真的不用管内存吗?从List< T>列表聊起
  3. 浅析C#编程中的内存管理
  4. .NET内存中敏感数据的保护方案
  5. 浅析.NET框架下的自动内存管理

相关内容

热门资讯

如何允许远程连接到MySQL数... [[277004]]【51CTO.com快译】默认情况下,MySQL服务器仅侦听来自localhos...
如何利用交换机和端口设置来管理... 在网络管理中,总是有些人让管理员头疼。下面我们就将介绍一下一个网管员利用交换机以及端口设置等来进行D...
施耐德电气数据中心整体解决方案... 近日,全球能效管理专家施耐德电气正式启动大型体验活动“能效中国行——2012卡车巡展”,作为该活动的...
Windows恶意软件20年“... 在Windows的早期年代,病毒游走于系统之间,偶尔删除文件(但被删除的文件几乎都是可恢复的),并弹...
20个非常棒的扁平设计免费资源 Apple设备的平面图标PSD免费平板UI 平板UI套件24平图标Freen平板UI套件PSD径向平...
德国电信门户网站可实时显示全球... 德国电信周三推出一个门户网站,直观地实时提供其安装在全球各地的传感器网络检测到的网络攻击状况。该网站...
着眼MAC地址,解救无法享受D... 在安装了DHCP服务器的局域网环境中,每一台工作站在上网之前,都要先从DHCP服务器那里享受到地址动...
为啥国人偏爱 Mybatis,... 关于 SQL 和 ORM 的争论,永远都不会终止,我也一直在思考这个问题。昨天又跟群里的小伙伴进行...