zoukankan      html  css  js  c++  java
  • 解决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 

  • 相关阅读:
    LeetCode "Palindrome Partition II"
    LeetCode "Longest Substring Without Repeating Characters"
    LeetCode "Wildcard Matching"
    LeetCode "Best Time to Buy and Sell Stock II"
    LeetCodeEPI "Best Time to Buy and Sell Stock"
    LeetCode "Substring with Concatenation of All Words"
    LeetCode "Word Break II"
    LeetCode "Word Break"
    Some thoughts..
    LeetCode "Longest Valid Parentheses"
  • 原文地址:https://www.cnblogs.com/yeahgis/p/2246332.html
Copyright © 2011-2022 走看看