1

I'm making an image-editing program in C#, and one of the functions I want to be able to have is to invert the colors.

As of currently, I have the following code which just loads the image and puts the color into a 2-d array:

 if (fd.ShowDialog() == DialogResult.OK)
            {
                    //store the selected file into a bitmap
                    bmp = new Bitmap(fd.FileName);

                    //create the arrays that store the colours for the image
                    //the size of the arrays is based on the height and width of the bitmap
                    //initially both the original and transformedPic arrays will be identical

                    original = new Color[bmp.Height, bmp.Width];
                    transformedPic = new Color[bmp.Height, bmp.Width];

                    //load each color into a color array
                    for (int i = 0; i < bmp.Height; i++)//each row
                    {
                        for (int j = 0; j < bmp.Width; j++)//each column
                        {
                            //assign the colour in the bitmap to the array
                            original[i, j] = bmp.GetPixel(j, i);
                            transformedPic[i, j] = original[i, j];
                        }
                    }
                    this.Refresh();
                }
             }

I'm completely stumped in regards to the concept of inverting colors and how I would manipulate the values in the 2-d array to reflect the inverted color of the pixel. I'm extremely new to programming, so any help would be greatly appreciated.

EDIT: (not working still)

 //code to invert
        byte A, R, G, B;
        Color pixelColor;

            for (int i = 0; i < bmp.Height; i++)
            {
                for (int j = 0; j < bmp.Width; j++)
                {
                        pixelColor = original[i, j];
                        A = (byte)Math.Abs(255 - pixelColor.A);
                        R = (byte)Math.Abs(255 - pixelColor.R);
                        G = (byte)Math.Abs(255 - pixelColor.G);
                        B = (byte)Math.Abs(255 - pixelColor.B);
                        bmp.SetPixel(i, j, Color.FromArgb((int)A, (int)R, (int)G, (int)B));
                        transformedPic[i, j] = bmp.GetPixel(i, j);
                }
            }  
Daniel A. White
  • 187,200
  • 47
  • 362
  • 445
rezon
  • 45
  • 6
  • 10
  • Possibly related to this [question](http://stackoverflow.com/questions/1165107/how-do-i-invert-a-colour-color-c-net) – juharr Apr 10 '15 at 17:33
  • 2
    Check out this question: http://stackoverflow.com/questions/1165107/how-do-i-invert-a-colour-color-c-net. Basically `newRGB = Color.FromRgb( 255 - oldRed, 255 - oldGreen, 255 - oldBlue)` – Sarah Apr 10 '15 at 17:34
  • @Sarah I was just writing basically the same thing :( You beat me to it! +1 – ProgrammingLlama Apr 10 '15 at 17:34
  • 2
    If you want your code to be fast, you should not loop through every pixel and use GetPixel/SetPixel. Instead, you should apply a `ColorMatrix` to the image. For an example, see [this question](http://stackoverflow.com/q/5096285/21727). – mbeckish Apr 10 '15 at 17:46
  • 1
    Better use LockBits and manipulate the memory – Gusman Apr 10 '15 at 17:53
  • @Sarah Thanks for the help, I digged through a few of the questions linked, and created some code in the edit of the OP. I'm still not there yet, and i'm not sure what i'm doing wrong. – rezon Apr 10 '15 at 17:55
  • @mbeckish Thanks for the help as well, but I think i'm not too worried about efficiency of code yet as I'm still a beginner. I looked at the question and I'm left with more questions than answers, so perhaps i'll look into that in the future, much appreciated however. – rezon Apr 10 '15 at 17:56
  • 1
    Do not invert the A channel - you should leave that intact. Otherwise you are turing a solid image into a completely transparent one. – Dan Byström Apr 28 '15 at 08:27

1 Answers1

0

To invert an entire image, try this:

var original = (BitmapSource)image;
var bmp = new WritableBitmap( original );
bmp.Lock();

var bgra = new byte[bmp.PixelHeight * bmp.PixelWidth * 4];

bitmap.CopyPixels( bgra, bmp.PixelWidth * 4, 0 );

for( var y = 0; y < bmp.PixelHeight; y++ )
  for( var x = 0; x < bmp.PixelWidth; x++ )
  {
    var offset = y * bmp.PixelWidth * 4 + x * 4;
    bgra[offset + 0] = (byte)(255 - bgra[offset + 0] );
    bgra[offset + 1] = (byte)(255 - bgra[offset + 1] );
    bgra[offset + 2] = (byte)(255 - bgra[offset + 2] );
  }

bmp.WritePixels( new Int32Rect( 0, 0, width, height ), bgra, bmp.PixelWidth * 4, 0 );
bmp.Unlock();
bmp.Freeze();
Sarah
  • 328
  • 1
  • 6
  • 15