当前位置: 首页 > 图文教程 > 网络编程 > ASP.NET > .Net中图片的快速处理

ASP.NET
ASP.NET开发:简化应用程序的开发支持Web标准
asp.net XMLHttpRequest实现用户注册前的验证
asp.net 页面间传值方法小结
asp.net url重写浅谈
asp.net 验证码生成和刷新及验证
C#精髓 GridView72大绝技 学习gridview的朋友必看
实例说明asp.net中的简单角色权限控制
asp.net网站开发包wq.dll打包下载
js与ASP.NET 中文乱码问题
asp.net checkbox 动态绑定id GridView删除提示
asp.net TextBox回车触发事件 图片在img显示
asp.net 脏字典过滤问题 用正则表达式来过滤脏数据
asp.NET 脏字过滤算法
asp.NET 脏字过滤算法 修改版
asp.net sql 数据库处理函数命令
asp.net Javascript 的几种写法与提示
ASP.NET MVC学习笔记
asp.net 中国身份证号码验证代码 非正则
Asp.net中使用Sqlite数据库的方法
asp.net 中文字符串提交乱码的解决方法

ASP.NET 中的 .Net中图片的快速处理


出处:互联网   整理: 软晨网(RuanChen.com)   发布: 2009-08-14   浏览: 106 ::
收藏到网摘: n/a

在图片处理过程中,我们经常需要对图片逐像素进行处理,比如为了使图片某一向量的颜色加深或者减淡,或者为了使图像变化成黑白颜色,这个时候我们需要取出每个点上的像素进行计算,再赋值到图像指定的位置。在.Net中,官方提供了Image.GetPixel(int x, int y)的方法供开发人员获取指定位置的像素,同时提供了Image.SetPixel(int x, int y, Color color)的方法来给指定位置的像素赋值。但是这个方法性能很差,假设存在一张1024*768的图片,逐像素操作并予以缓存的话亦至少需要1027*768次GetPixel和SetPixel,处理速度将慢到无法忍受。因此本方案将使用对内存直接读取和赋值的方式来提高图片处理的速度。

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

使用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)来解锁内存就可以了,例如:

以下为引用的内容:
        private void LockUnlockBitsExample(PaintEventArgs e)
        {
            Bitmap bmp 
= new Bitmap("c:\\fakePhoto.jpg");
            Rectangle rect 
= new Rectangle(00, bmp.Width, bmp.Height);
            System.Drawing.Imaging.BitmapData bmpData 
=
                bmp.LockBits(rect, System.Drawing.Imaging.ImageLockMode.ReadWrite,
                bmp.PixelFormat);
            IntPtr ptr 
= bmpData.Scan0;
            
int bytes = bmp.Width * bmp.Height * 3;
            
byte[] rgbValues = new byte[bytes];
            
for (int counter = 0; counter < rgbValues.Length; counter += 3)
            {
                Marshal.WriteByte(ptr, counter, 
255);
            }
            bmp.UnlockBits(bmpData);
            e.Graphics.DrawImage(bmp, 
00);
        }

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

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

以下为引用的内容:
    [StructLayout(LayoutKind.Explicit)]
    
public struct ColorBgra
    {
        [FieldOffset(
0)]
        
public byte B;
 
        [FieldOffset(
1)]
        
public byte G;
 
        [FieldOffset(
2)]
        
public byte R;
 
        [FieldOffset(
3)]
        
public byte A;

        
/// <summary>
        
/// Lets you change B, G, R, and A at the same time.
        
/// </summary>
        [FieldOffset(0)]
        
public uint Bgra;
        
public override string ToString()
        {
            
return "B: " + B + ", G: " + G + ", R: " + R + ", A: " + A;
        }
    }

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

以下为引用的内容:
        public unsafe ColorBgra* GetPointAddress(int x, int y)
        {
            
return y * 4 + x;
        }

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

以下为引用的内容:
                    color->= i;
                    color 
->= i;
                    color 
->= i;
                    color 
->= i;

直接把值写入内存中,实现对图片像素的快速操作。