• 解决GDI+中“内存不足”问题


    近日用GDI+做一个图片处理的小程序,需要实现调整图片的亮度、对比度、饱和度和Gamma值的功能。一开始试验逐个像素的处理,可是对于一副2592*1944的普通数码照片来说处理一副图像竟然将近20秒,无法忍受,需要寻找效率更高的方法。研究了下MSDN,发现.net给我们提供了一个更为方便的方法,就是使用颜色矩阵(ColorMatrix),或者称为颜色变换矩阵,位于System.Drawing.Imaging命名空间下。.net为我们对图形图像的变换、调节等操作进行了优化,对于一副2592*1944的普通数码照片,要达到同样的效果大约不到逐个像素处理方法的1/10的时间即可完成。

          问题来了。在运用颜色变换矩阵的时候有一点需要特别注意:定义的Image对象可以是来自于文件(FromFile方法),也可以是来自于数据流(FromStream方法,数据流可以是根据文件建立的文件数据流,也可以是内存中的数据流即MemoryStream),但是不可以是来自于PictureBox的Image属性,后者的像素格式不受Graphics类支持的。否则使用Graphics类的DrawImage方法生成新的图像时就会产生“内存不足”的错误。如果你的原始图像文件的像素格式也不受支持的话,即使是数据流来自于文件或者内存中也会产生这个问题。归根结底还是在Graphics类中操作了具有不被支持的像素格式的图像。使用PictureBox的Image属性新建一个Image对象是完全可以的,并且获取的也是当前PictureBox中的图像,一开始使用这个方法,Image总是来自于PictureBox,总是产生“内存不足”的错误,困扰了好大一会儿。

          那怎样获取具有被Graphics类支持的像素格式的当前PictureBox中显示的图像的数据流呢?我是通过将PictureBox中显示的图像暂存在本地硬盘临时文件夹中,再用一个不显示的OpenFileDialog读取这个文件获取到的。当然一涉及到硬盘的I/O操作,性能肯定会降低。应该也可以在内存中进行相应的操作获取这个图像的数据流,那样应该会快一点,但是对系统的内存要求就稍微高一点,孰优孰劣,视具体应用情况而定吧。

         解决了这个问题,接下来就是设计变换矩阵了,没什么好说的,基础知识就是线性代数中的矩阵运算,想快点就查MSDN吧。呵呵。

    备案:亮度

    float[][] matrix = { 
          new float[] { 1, 0, 0, 0, 0 }, 
          new float[] { 0, 1, 0, 0, 0 }, 
          new float[] { 0, 0, 1, 0, 0 }, 
          new float[] { 0, 0, 0, 1, 0 }, 
          new float[] { v, v, v, 0, 1 } 
    };

    对比度:      float[][] matrix = { 
                            new float[] { scale, 0, 0, 0, 0 }, 
                            new float[] { 0, scale, 0, 0, 0 }, 
                            new float[] { 0, 0, scale, 0, 0 }, 
                            new float[] { 0, 0, 0, 1, 0 }, 
                            new float[] { -offset, -offset, -offset, 0, 1 } 
                        };

    饱和度:

                            float[][] matrix = { 
                                new float[] { red + v, red, red, 0, 0 }, 
                                new float[] { green, green + v, green, 0, 0}, 
                                new float[] { blue, blue, blue + v, 0, 0 }, 
                                new float[] { 0, 0, 0, 1, 0}, 
                                new float[] {0, 0, 0, 0, 1 } 
                            };

    Gamma值比较简单,设置一个参数就可以了。

    2009-09-06 19:25 

  • 相关阅读:
    Java 抽象类
    Java 多态
    Java 重写与重载
    Java继承
    声卡驱动
    Sublime Text 3快捷键
    近年来世界各地ICO的花式骗局盘点
    区块链未能大爆发的影响因素有哪些?
    BCH分叉是一次站队博弈
    一文读懂百倍币的诞生背景
  • 原文地址:https://www.cnblogs.com/yeahgis/p/2246332.html
Copyright © 2020-2023  润新知