浅谈.NET图片快速处理的几种方法

开发 后端
在.NET图片快速处理过程中,我们经常需要对图片逐像素进行处理,比如为了使图片某一向量的颜色加深或者减淡,或者为了使图像变化成黑白颜色,这个时候我们需要取出每个点上的像素进行计算,再赋值到图像指定的位置。

这里首先要介绍一个类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. /// <summary> 
  17. /// Lets you change B, G, R, and A at the same time.  
  18. /// </summary> 
  19. [FieldOffset(0)]  
  20. public uint Bgra;  
  21. public override string ToString()  
  22. {  
  23. return "B: " + B + ", G: " + G + ", R: " + R + ", A: " + A;  
  24. }  

使用这个类在声明为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框架下的自动内存管理
责任编辑:彭凡 来源: cnblogs
相关推荐

2013-08-21 11:31:21

iPhone图片方法

2009-07-20 17:07:30

提高ASP.NET性能

2009-09-18 09:16:06

.NET垃圾回收

2010-09-08 13:53:10

.NET连接Sybas

2009-09-04 11:20:47

ASP.NET页面间值

2011-09-06 16:56:43

2010-06-03 08:55:43

LINQ

2009-12-16 09:16:53

ASP.NET页面间数

2019-12-12 21:45:17

javascript前端css

2020-01-10 16:23:44

Springboot停止服务Java

2009-09-09 11:24:46

PHP实现MVC

2009-08-31 09:19:31

c#隐藏窗口

2011-06-16 10:48:33

session

2021-02-26 13:20:48

Shell空行Linux

2020-08-24 08:05:47

JavaScriptJavaScript 页面

2009-09-18 12:29:55

2010-05-17 15:17:06

MySQL常用操作

2009-10-26 10:30:57

VB.NET处理FTP

2015-10-12 11:06:36

Web前端0.5像素

2022-02-17 09:12:55

MySQL数据库设置变量
点赞
收藏

51CTO技术栈公众号