C# Tutorial: How To Flip an Image Horizontally
Where Do We Start? There are numerous ways you can flip an image horizontally. It’s pretty basic functionality in image processing. I wanted to challenge myself and not just...
Filter by Category
Where Do We Start? There are numerous ways you can flip an image horizontally. It’s pretty basic functionality in image processing. I wanted to challenge myself and not just...
Let’s Get Started A very basic problem that we face in image processing is how to scale images without making them look deformed when we want to make it of an arbitrary...
List of contents: Short intro First Method – Google Opinion Rewards Second Method – Taking & Fortifying Gyms Third Method – Answer a Few Questions List of...
Zero padding an image is useful when we’re convolving it with a filter of certain size. How much padding should we use depends on how big our filter is. What is the purpose...
Gamma correction is a process, which allows you to set the brightness of screen. You can often run into this setting in video games, where you set the brightness of your screen...
A negative image is a complete inversion of an image, we would say to be normal. In other words, dark areas will appear light, and light areas will become dark. More in detail, a...
Gaussian blur is an image processing operation, that reduces noise in images. It does so by a convolution process, using a matrix that contains values calculated by a Gaussian...
Erosion is a morphological process, where pixels at an object boundaries are removed. Erosion and dilation are a pair of basic morphological transformations, which are completely...
Dilation is a simple morphology process which changes pixel intensities based on the change of intensities that occur at object boundaries. This process is used on grayscale...
What is sobel operator? Well, basically it’s 2 kernels, with which we can process an image in a way, that only edges are visible. It is commonly used for grayscale images,...
There are numerous ways you can flip an image horizontally. It’s pretty basic functionality in image processing. I wanted to challenge myself and not just use the preexisting line of code that takes care of this functionality entirely. So I coded entire thing myself, well, at least some level closer to the base anyway.
To mirror an image horizontally I used the “lockbits” method, where I rearranged pixel values stored in a one dimensional array. The problem we face here is that we only want to flip pixel values along horizontal axis while rows stay in the same order. So what we need to do is separate rows and columns somehow.
Luckily, we know that a row has a length of one “Stride” value and each pixel holds 4 values (red, green, blue and alpha values). With that in mind, we will nest 3 for loops within each other.
Like this:
for ( ... ){ for( ... ){ for( ... ){ some code... } } }
Now we need to create a variable that will get the position for any pixel in the array of pixel values. So, the nested for loops we created will help us keep track of what exact value we are processing. Most inner for loop will iterate through RGB values, the middle and most outer loop will iterate through horizontal and vertical position of the pixels.
Now the last thing we need, are limits for each for loop to work. For RGB for loop we declare the limit to be 3, as there are values for red, green and blue color channel. This is a constant number, which means it’s applied for every image we are processing. The fourth pixel value, alpha channel, which controls the opacity of each pixel will be set to it’s maximum. We are processing 32-bit images so the maximum for each value is 255. 32 times 4 values is 256 possible values for each channel. 255 is the maximum value, because counting starts with 0.
Limits for horizontal and vertical values are the dimensions of the image we are processing. Remember not to mix Stride and Width of the image, since Stride includes each pixel values while Width of the image holds only the number of pixels in a row.
Now that we know about all the numbers we are working with, we can return to the variable that will tell us which pixel we are processing.
On the vertical or “y” coordinate we will move with “y * Stride”. “y” is the variable which we are iterating. To move along the horizontal or “x” coordinate we will use “x * 4”. “x” being the variable that is being iterated and 4, which stands for 4 channels for each pixel.
Now if we put it together, it should look something like this:
current_pixel = y * sourceData.Stride + x * 4;
private Bitmap HorizontalFlip(Bitmap img) { int w = img.Width; int h = img.Height; BitmapData sd = img.LockBits(new Rectangle(0, 0, w, h), ImageLockMode.ReadWrite, PixelFormat.Format32bppArgb); int bytes = sd.Stride * sd.Height; byte[] buffer = new byte[bytes]; byte[] result = new byte[bytes]; Marshal.Copy(sd.Scan0, buffer, 0, bytes); img.UnlockBits(sd); int current, flipped = 0; for (int y = 0; y < h; y++) { for (int x = 4; x < w; x++) { current = y * sd.Stride + x * 4; flipped = y * sd.Stride + (w - x) * 4; for (int i = 0; i < 3; i++) { result[flipped + i] = buffer[current + i]; } result[flipped + 3] = 255; } } Bitmap resimg = new Bitmap(w, h); BitmapData rd = resimg.LockBits(new Rectangle(0, 0, w, h), ImageLockMode.WriteOnly, PixelFormat.Format32bppArgb); Marshal.Copy(result, 0, rd.Scan0, bytes); resimg.UnlockBits(rd); return resimg; }