Login | Register

Nerd Paradise

Now with 15% less sodium!

Editing Images in WPF / C# / .NET

Post by: Blake
Posted on: 10 Cado 8:3 - 18.5.81
For some reason it's so hard to find a simple, to-the-point reference on how to edit regular 32-bit images in WPF, especially considering WPF's lack of a built in image editing library. So here's the most basic sample code for editing an image from scratch programmatically. This is only applicable to WPF projects.


using System.Windows;
using System.Windows.Media;
using System.Windows.Media.Imaging;

namespace ImageEditing
    public partial class Window1 : Window
        public Window1()

            int width = 300;
            int height = 300;

            // Create a writeable bitmap (which is a valid WPF Image Source
            WriteableBitmap bitmap = new WriteableBitmap(width, height, 96, 96, PixelFormats.Bgra32, null);

            // Create an array of pixels to contain pixel color values
            uint[] pixels = new uint[width * height];

            int red;
            int green;
            int blue;
            int alpha;

            for (int x = 0; x < width; ++x)
                for (int y = 0; y < height; ++y)
                    int i = width * y + x;

                    red = 0;
                    green = 255 * y / height;
                    blue = 255 * (width - x) / width;
                    alpha = 255;

                    pixels[i] = (uint)((blue << 24) + (green << 16) + (red << 8) + alpha);
            // apply pixels to bitmap
            bitmap.WritePixels(new Int32Rect(0, 0, 300, 300), pixels, width * 4, 0);

            // set image source to the new bitmap
            this.MainImage.Source = bitmap;


<Window x:Class="ImageEditing.Window1"
    Title="Window1" Height="300" Width="300">
        <Image x:Name="MainImage"/>

And the result...


As a side note, you don't need to modify all the pixels simultaneously. If you want to modify a smaller region, you can pass in a smaller array of uints to the WritePixels method. The stride parameter for WritePixels is the number of BYTES across your array is PER ROW. As long as the pixel array you passed in has a length that is divisible by the stride divided by 4 and is in sync with the Int32Rect you passed in as the first parameter, you can modify any rectangular region as you wish to optimize your edits.

So there you have it: The sample code for doing basic image manipulation in C#, .NET, WPF, whatever. This really opens up doors for you. For example, based on mouse down/up/move events, you could easily make an mspaint clone. Or your own photo optimizing program based on RGB number crunching. Or just simple scripts such as converting a white-black image into a transparent-black image. Or perhaps you can make your own grand 2D Graphics library for WPF that you sell for lots of money. But those all sound like really good NP posts, so stay tuned.
facebook twitter Stumbleupon Reddit del.icio.us Digg
User Comments: 4
Post by Pgrammer on 12 Ineo 1:3 - 16.90.35
I'm trying to port a GDI+ application to WPF. The first part of this example helped but I still can't write to a Bitmap the way I need to. The current code uses a Graphics object: Graphics.DrawImage(...) to draw on the Bitmap. Do you know of a way to convert this code to WPF using your method? Is it possible to do this with WriteableBitmap?


int sx = (selectedPaletteTile % PALETTE_COLUMNS) * 33;
int sy = (selectedPaletteTile / PALETTE_COLUMNS) * 33;
Rectangle src = new Rectangle(sx, sy, 32, 32); // Source
Rectangle dst = new Rectangle(0, 0, 32, 32); // Destination
gfx.DrawImage(imgPalette.Source, dst, src, draw.GraphicsUnit.Pixel);
Post by TheRaffy on 14 Vigeo 7:4 - 8.31.55
Thank you for the code. It helped a lot! But it seems there is a little mistake in the color order.

This way it works better:
pixels[i] = (uint)((alpha << 24) + (red << 16) + (green << 8) + blue);

Post by ikanreed on 14 Vigeo 9:0 - 9.48.84
TheRaffy said:
Thank you for the code. It helped a lot! But it seems there is a little mistake in the color order.

This way it works better:
pixels[i] = (uint)((alpha << 24) + (red << 16) + (green << 8) + blue);


Careful now. If your inputs aren't sanitized, and alpha could be 256 or greater, this will throw an exception.
Post by next525 on 16 Vigeo 12:5 - 7.81.92
I'm new and I'm interested in this topic. Thank you!
You must be logged in to add a comment
Current Date: 16 Vigeo 13:3Current Time: 3.35.43Join us in IRC...
Server: irc.esper.net
Channel: #nerdparadise
Your IP: UnknownBrowser Version: 0