Other Posts in Image Editing

  1. Perlin Noise
  2. Fault Formation
  3. Cellular Textures
  4. Resizing an Image in C#
  5. Box Blur and Gaussian Blur... Sort of...
  6. Thermal Erosion
  7. Using Mid Point Displacement to Create Cracks
  8. Fluvial Erosion
  9. Creating Marble Like Textures Procedurally
  10. Procedural Textures and Dilation
  11. Converting Image to Black and White in C#
  12. Getting an HTML Based Color Palette from an Image in C#
  13. Adding Noise/Jitter to an Image in C#
  14. Creating Pixelated Images in C#
  15. Edge detection in C#
  16. Using Sin to Get What You Want... In C#...
  17. Noise Reduction of an Image in C# using Median Filters
  18. Image Dilation in C#
  19. Sepia Tone in C#
  20. Kuwahara Filter in C#
  21. Matrix Convolution Filters in C#
  22. Symmetric Nearest Neighbor in C#
  23. Bump Map Creation Using C#
  24. Normal Map Creation Using C#
  25. Creating Negative Images using C#
  26. Red, Blue, and Green Filters in C#
  27. Converting an Image to ASCII Art in C#
  28. Adjusting Brightness of an Image in C#
  29. Adding Noise to an Image in C#
  30. Adjusting the Gamma of an Image Using C#
  31. Adjusting Contrast of an Image in C#
  32. Drawing a Box With Rounded Corners in C#
  33. Anding Two Images Together Using C#
  34. Motion Detection in C#
  35. Creating Thermometer Chart in C#
  36. Colorizing a Black and White Image in C#
  37. Extracting an Icon From a File
  38. Setting the Pixel Format and Image Format of an Image in .Net
  39. Using Unsafe Code for Faster Image Manipulation
  40. Sobel Edge Detection and Laplace Edge Detection in C#

Creating Pixelated Images in C#


If you read my site for any length of time, you'll notice that I tend to post a lot on things like image manipulation, image recognition, video processing (in the future anyway), etc. To be honest I find the field to be rather interesting and have even started working on incorporating OpenCV into the project I'm working on... Anyway, I'm starting to add some more "fun" items to my library. No real practical use, just there for the sake of being there really. In this instance I wanted to simply create a pixelated cookie monster... I'm not going into why I wanted to create this, but it's for an April Fools joke. Anyway, I decided instead of doing the easy thing (opening up Photoshop) that I'd do it the hard way and use C#.

   1: /// <summary>
   2: /// Pixelates an image
   3: /// </summary>
   4: /// <param name="OriginalImage">Image to pixelate</param>
   5: /// <param name="PixelSize">Size of the "pixels" in pixels</param>
   6: /// <returns>A bitmap which is pixelated</returns>
   7: public static Bitmap Pixelate(Bitmap OriginalImage, int PixelSize)
   8: {
   9:     Bitmap NewBitmap = new Bitmap(OriginalImage.Width, OriginalImage.Height);
  10:     BitmapData NewData = Image.LockImage(NewBitmap);
  11:     BitmapData OldData = Image.LockImage(OriginalImage);
  12:     int NewPixelSize = Image.GetPixelSize(NewData);
  13:     int OldPixelSize = Image.GetPixelSize(OldData);
  14:     for (int x = 0; x < NewBitmap.Width; x += (PixelSize / 2))
  15:     {
  16:         int MinX = MathHelper.Clamp(x - (PixelSize / 2), NewBitmap.Width, 0);
  17:         int MaxX = MathHelper.Clamp(x + (PixelSize / 2), NewBitmap.Width, 0);
  18:         for (int y = 0; y < NewBitmap.Height; y += (PixelSize / 2))
  19:         {
  20:             int RValue = 0;
  21:             int GValue = 0;
  22:             int BValue = 0;
  23:             int MinY = MathHelper.Clamp(y - (PixelSize / 2), NewBitmap.Height, 0);
  24:             int MaxY = MathHelper.Clamp(y + (PixelSize / 2), NewBitmap.Height, 0);
  25:             for (int x2 = MinX; x2 < MaxX; ++x2)
  26:             {
  27:                 for (int y2 = MinY; y2 < MaxY; ++y2)
  28:                 {
  29:                     Color Pixel = Image.GetPixel(OldData, x2, y2, OldPixelSize);
  30:                     RValue += Pixel.R;
  31:                     GValue += Pixel.G;
  32:                     BValue += Pixel.B;
  33:                 }
  34:             }
  35:             RValue = RValue / (PixelSize * PixelSize);
  36:             GValue = GValue / (PixelSize * PixelSize);
  37:             BValue = BValue / (PixelSize * PixelSize);
  38:             Color TempPixel = Color.FromArgb(RValue, GValue, BValue);
  39:             for (int x2 = MinX; x2 < MaxX; ++x2)
  40:             {
  41:                 for (int y2 = MinY; y2 < MaxY; ++y2)
  42:                 {
  43:                     Image.SetPixel(NewData, x2, y2, TempPixel, NewPixelSize);
  44:                 }
  45:             }
  46:         }
  47:     }
  48:     Image.UnlockImage(NewBitmap, NewData);
  49:     Image.UnlockImage(OriginalImage, OldData);
  50:     return NewBitmap;
  51: }

Actually that isn't that difficult really. The code above takes in a Bitmap object and the size of the individual pixels. It then does one pass over a section of that image (a section is the size in pixels specified), finds the average image color, and does another pass setting the pixels to that value. Once it's done with the image it breaks out of the loop and returns a new version of the bitmap in its pixelated glory. A couple things to note is the fact that the code uses a couple of functions from my utility library to Lock/Unlock the images in order to speed things up a bit. You can simply remove them and replace the SetPixel/GetPixel function with the built in function. Anyway, I hope this helps out someone out there. So try out the code, leave feedback, and happy coding.


November 13, 2011 3:07 PM

I'm bad about going back and editing posts. But yes, if you go to the utility library's page (cul.codeplex.com), it should have all the code needed in the source code section. And I'll take a look at the edge pixel issues... It's probably, as you said, just that the bounds are off.

November 04, 2011 1:30 PM
James-Thanks for this. I had two issues.1. In the 2.2 cul, Image.GetPixelSize, LockImage, SetPixel and UnlockImage are not accessible. Made it difficult to work with this, and other, snippets from your blog. [This appears to be is corrected in the repository trunk.]2. The second issue is the loop bounds appear to be "off". The edge pixels are "light" (top and left) and "dark" (bottom and right).[First attempt to save my comment with more technical detail failed.]FWIW,Kevin