The source code for this article is available at the Gigi Labs BitBucket repository. It’s the same as in the Grayscale article, plus the code for the Negative effect in this article.
In “Converting an Image to Grayscale using SDL2”, we manipulated the pixels of an existing image in order to convert it to grayscale. It is now very easy to add all sorts of effects by changing pixel values in different ways.
Another effect we can apply is the Negative of an image. This means that the dark areas become light, and the light areas become dark. For instance, if we have this image of a Canadian goose:
By using any image editor, say Irfanview, we can get the following Negative:
This is a very easy effect to apply. Since each of the Red, Green and Blue channels is represented by a byte, its value is in the range between 0 and 255. So we can compute the Negative by subtracting each value from 255. That way a bright value (e.g. 210) will become dark (e.g. 45), and vice versa.
Here’s the code for the Negative image effect:
case SDLK_n: for (int y = 0; y < image->h; y++) { for (int x = 0; x < image->w; x++) { Uint32 pixel = pixels[y * image->w + x]; Uint8 r = pixel >> 16 & 0xFF; Uint8 g = pixel >> 8 & 0xFF; Uint8 b = pixel & 0xFF; r = 255 - r; g = 255 - g; b = 255 - b; pixel = (0xFF << 24) | (r << 16) | (g << 8) | b; pixels[y * image->w + x] = pixel; } } break;
The code for Negative is very similar to Grayscale in that we’re looping over each pixel, calculating new values for Red, Green and Blue, and then applying the new value to the pixel.
Let’s try this out with a photo I took of Eldon House in London, Canada last September. Here’s the photo in its normal state:
When I press the N key to apply the Negative effect, here’s the result:
I can also press N again to apply Negative on the Negative, and end up with the original image again:
That’s an important difference between Grayscale and Negative. Grayscale is an operation that loses colour information, and you can’t go back. Negative, on the other hand, is symmetric, and you can go back to the original image simply by applying the same operation again.