0

I need to reduce the brightness of the picture using c#. After some analysis i have found one solution to reduce the brightness of the image by adjusting its each pixel color RGB values. Please find the codes from below:

        Bitmap bmp = new Bitmap(Picture);
        Reduce the picture color brightness
        for (int i = 0; i < bmp.Width; i++)
        {
            for (int j = 0; j < bmp.Height; j++)
            {
                Color color = bmp.GetPixel(i, j);
                color = ChangeColorBrightness(color, 0.80f);
                bmp.SetPixel(i, j, color);
            }
        }

Method to reduce the RGB values of particular color:

    private Color ChangeColorBrightness(Color color, float correctionFactor)
    {
        float red = (float)color.R;
        float green = (float)color.G;
        float blue = (float)color.B;

        if (correctionFactor < 0)
        {
            correctionFactor = 1 + correctionFactor;
            red *= correctionFactor;
            green *= correctionFactor;
            blue *= correctionFactor;
        }
        else
        {
            red = (255 - red) * correctionFactor + red;
            green = (255 - green) * correctionFactor + green;
            blue = (255 - blue) * correctionFactor + blue;
        }

        return Color.FromArgb(color.A, (int)red, (int)green, (int)blue);
    }

This codes are working fine for my requirement but it will takes such amount of time when i am executing huge number of images with larger width and height. Is there any other possibilities to achieve this requirement?

Uwe Keim
  • 39,551
  • 56
  • 175
  • 291
Vijay
  • 78
  • 1
  • 10
  • 1
    Rather than set each pixel, re-draw the image on to a new one with the adjustments you need. [This answer](http://stackoverflow.com/a/15408608/2009) shows how to adjust brightness, contrast, and gamma in one shot. – hometoast Oct 11 '16 at 11:35
  • Thank you for your suggestion. But i didn't like to use the Graphics object within my implementation. So that i am ignoring the way by using the color matrix. – Vijay Oct 11 '16 at 12:06

1 Answers1

1

.GetPixel() and .SetPixel() are expensive - here is a faster appraoch

public static Bitmap ChangeColorBrightness(Bitmap bmp, float correctionFactor)
{  
    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 = Math.Abs(bmpData.Stride) * bmp.Height;
    byte[] rgbValues = new byte[bytes];
    System.Runtime.InteropServices.Marshal.Copy(ptr, rgbValues, 0, bytes); 
    float correctionFactortemp = correctionFactor;
    if (correctionFactor < 0)
    {
        correctionFactortemp = 1 + correctionFactor;
    }
    for (int counter = 1; counter < rgbValues.Length; counter ++)
    {
        float color = (float)rgbValues[counter];
        if (correctionFactor < 0)
        {
            color *= (int)correctionFactortemp;
        }
        else
        {
            color = (255 - color) * correctionFactor + color;                  
        }
        rgbValues[counter] = (byte)color;          
    }
    System.Runtime.InteropServices.Marshal.Copy(rgbValues, 0, ptr, bytes);
    bmp.UnlockBits(bmpData);
    return bmp;
}
fubo
  • 44,811
  • 17
  • 103
  • 137
  • I don't like to use graphics object in my implementation. Is there any possibilities without graphics object? – Vijay Oct 11 '16 at 12:30
  • @VijayR, it's like you're asking, "what is the fast way to do this, but don't tell me the most common way to make it fast" – hometoast Oct 11 '16 at 15:07
  • The recommend way is to use a Color Matrix. Working with Winforms graphics will usually imply a Graphics object. Not 'liking' it is irrational. In this solution though the use of a Graphics object is completely unnecessary and does nothing at all. – TaW Oct 11 '16 at 15:41
  • 1
    @TaW you're right, removed that – fubo Oct 12 '16 at 06:05