查看: 5994|回复: 0
打印 上一主题 下一主题

ASP.Net中图片的快速处理

[复制链接]
跳转到指定楼层
1#
发表于 2009-7-31 13:14:55 | 只看该作者 回帖奖励 |倒序浏览 |阅读模式
台州网址导航
在图片处理过程中,我们经常需要对图片逐像素进行处理,比如为了使图片某一向量的颜色加深或者减淡,或者为了使图像变化成黑白颜色,这个时候我们需要取出每个点上的像素进行计算,再赋值到图像指定的位置。在.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(0, 0, 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, 0, 0);
        }


此示例将图片上所有像素的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->B = i;
                    color ->G = i;
                    color ->R = i;
                    color ->A = i;


直接把值写入内存中,实现对图片像素的快速操作。
分享到:  QQ好友和群QQ好友和群 QQ空间QQ空间 腾讯微博腾讯微博 腾讯朋友腾讯朋友
收藏收藏 转播转播 分享分享 分享淘帖
台州维博网络(www.tzweb.com)专门运用PHP+MYSQL/ASP.NET+MSSQL技术开发网站门户平台系统等。
您需要登录后才可以回帖 登录 | 注册

本版积分规则

网站推广
关于我们
  • 台州朗动科技(Tzweb.com)拥有多年开发网站平台系统门户手机客户端等业务的成功经验。主要从事:政企网站,系统平台,微信公众号,各类小程序,手机APP客户端,浙里办微应用,浙政钉微应用、主机域名、虚拟空间、后期维护等服务,满足不同企业公司的需求,是台州地区领先的网络技术服务商!

Hi,扫描关注我

Copyright © 2005-2026 站长论坛 All rights reserved

Powered by 站长论坛 with TZWEB Update Techonolgy Support

快速回复 返回顶部 返回列表