通过GDI +图像对比度/伽玛/亮度

时间:2016-03-30 11:18:05

标签: c# gdi+

更新:将代码更改为较新版本。

我在stackoverflow上找到了一些代码,但不是很满意。我对GDI +不太熟悉,所以这可能是一个愚蠢的问题。

我有一个类来设置亮度/对比度/ Gamma:

public class ImageManipulation : IDisposable
{
    Bitmap _internalBitmapMemory;

    public ImageManipulation(Bitmap bitmap)
    {
        _internalBitmapMemory = new Bitmap(bitmap);
    }

    public Bitmap AdjustContrast(float Contrast = 1, float Brightness = 1, float Gamma = 1)
    {
        float brightness = Brightness;      // no change in brightness
        float contrast = Contrast;          // twice the contrast
        float gamma = Gamma;                // no change in gamma

        float adjustedBrightness = brightness - 1.0f;

        // create matrix that will brighten and contrast the image
        float[][] ptsArray =
        {
            new float[] {contrast,              0,                      0,                      0,                  0},     // scale red
            new float[] {0,                     contrast,               0,                      0,                  0},     // scale green
            new float[] {0,                     0,                      contrast,               0,                  0},     // scale blue
            new float[] {0,                     0,                      0,                      1.0f,               0},     // don't scale alpha
            new float[] {adjustedBrightness,    adjustedBrightness,     adjustedBrightness,     0,                  1}
        };

        var imageAttributes = new ImageAttributes();

        imageAttributes.ClearColorMatrix();
        imageAttributes.SetColorMatrix(new ColorMatrix(ptsArray), ColorMatrixFlag.Default, ColorAdjustType.Bitmap);
        imageAttributes.SetGamma(gamma, ColorAdjustType.Bitmap);

        Graphics g = Graphics.FromImage(_internalBitmapMemory);

        g.DrawImage(_internalBitmapMemory, new Rectangle(0, 0, _internalBitmapMemory.Width, _internalBitmapMemory.Height)
            , 0, 0, _internalBitmapMemory.Width, _internalBitmapMemory.Height,
            GraphicsUnit.Pixel, imageAttributes);

        g.Dispose();

        return _internalBitmapMemory;
    }

    public void Dispose()
    {
        _internalBitmapMemory.Dispose();
        _internalBitmapMemory = null;
    }
}

现在我遇到了一些问题:

1)n次迭代后性能变得越来越低。 2)如果GC太慢而无法清除内存,则会对内存进行爆破。我现在尝试通过使用类并使用using语句创建引用来解决此问题。

到目前为止这是有效的,但现在我的图像在显示之前就被处理掉了。 GRML!

如何优化/使其运行整个过程?

1 个答案:

答案 0 :(得分:-1)

我明白了。没什么大不了的,但是那个图形对象有些混乱:

Bitmap _bitmap;

private void BuildImage()
{
    using (ImageManipulation cls = new ImageManipulation(_bitmap))
    {
        ImageBox.Image.Dispose();
        ImageBox.Image = (Bitmap)cls.AdjustContrast((float)nudContrast.Value, (float)nudBrightness.Value, (float)nudGamma.Value).Clone();
    }
}

public class ImageManipulation : IDisposable
{
    Bitmap _internalBitmapMemory;

    public ImageManipulation(Bitmap bitmap)
    {
        _internalBitmapMemory = new Bitmap(bitmap);
    }

    public Bitmap AdjustContrast(float Contrast = 1, float Brightness = 1, float Gamma = 1)
    {
        float brightness = Brightness;      // no change in brightness
        float contrast = Contrast;          // twice the contrast
        float gamma = Gamma;                // no change in gamma

        float adjustedBrightness = brightness - 1.0f;

        // create matrix that will brighten and contrast the image
        float[][] ptsArray =
        {
            new float[] {contrast,              0,                      0,                      0,                  0},     // scale red
            new float[] {0,                     contrast,               0,                      0,                  0},     // scale green
            new float[] {0,                     0,                      contrast,               0,                  0},     // scale blue
            new float[] {0,                     0,                      0,                      1.0f,               0},     // don't scale alpha
            new float[] {adjustedBrightness,    adjustedBrightness,     adjustedBrightness,     0,                  1}
        };

        var imageAttributes = new ImageAttributes();

        imageAttributes.ClearColorMatrix();
        imageAttributes.SetColorMatrix(new ColorMatrix(ptsArray), ColorMatrixFlag.Default, ColorAdjustType.Bitmap);
        imageAttributes.SetGamma(gamma, ColorAdjustType.Bitmap);

        Graphics g = Graphics.FromImage(_internalBitmapMemory);

        g.DrawImage(_internalBitmapMemory, new Rectangle(0, 0, _internalBitmapMemory.Width, _internalBitmapMemory.Height)
            , 0, 0, _internalBitmapMemory.Width, _internalBitmapMemory.Height,
            GraphicsUnit.Pixel, imageAttributes);

        g.Dispose();

        return _internalBitmapMemory;
    }

    public void Dispose()
    {
        _internalBitmapMemory.Dispose();
        _internalBitmapMemory = null;
    }
}

关于mem-leak的问题是图片框,如果您添加新图像但是将其保留在内存中直到GC将清理混乱,则不会自动处理图像。

现在它按预期工作。

如果图像不仅仅用于在图片框上显示,那么可能应该做的是添加深拷贝。