One way to do this is to use the BitmapDecoder class to get raw pixel data. Then you can change the pixels and build a new WriteableBitmap from the modified pixel data:
// Copy pixel colour values from existing image. // (This loads them from an embedded resource. BitmapDecoder can work with any Stream, though.) StreamResourceInfo x = Application.GetResourceStream(new Uri(BaseUriHelper.GetBaseUri(this), "Image.png")); BitmapDecoder dec = BitmapDecoder.Create(x.Stream, BitmapCreateOptions.None, BitmapCacheOption.Default); BitmapFrame image = dec.Frames[0]; byte[] pixels = new byte[image.PixelWidth * image.PixelHeight * 4]; image.CopyPixels(pixels, image.PixelWidth*4, 0); // Modify the white pixels for (int i = 0; i < pixels.Length/4; ++i) { byte b = pixels[i * 4]; byte g = pixels[i * 4 + 1]; byte r = pixels[i * 4 + 2]; byte a = pixels[i * 4 + 3]; if (r == 255 && g == 255 && b == 255 && a == 255) { // Change it to red. g = 0; b = 0; pixels[i * 4 + 1] = g; pixels[i * 4] = b; } } // Write the modified pixels into a new bitmap and use that as the source of an Image var bmp = new WriteableBitmap(image.PixelWidth, image.PixelHeight, image.DpiX, image.DpiY, PixelFormats.Pbgra32, null); bmp.WritePixels(new Int32Rect(0, 0, image.PixelWidth, image.PixelHeight), pixels, image.PixelWidth*4, 0); img.Source = bmp;
It works after the mod, but there is a problem. Here's what the result looks like if I show it on a dark background:

As you can see, he had some kind of white border. What happened here is that your white cross had smoothed edges, which means that the pixels around the edges are actually a translucent shade of gray.
We can handle this using a slightly more sophisticated technique in the pixel modification loop:
if ((r == 255 && g == 255 && b == 255 && a == 255) || (a != 0 && a != 255 && r == g && g == b && r != 0)) { // Change it to red. g = 0; b = 0; pixels[i * 4 + 1] = g; pixels[i * 4] = b; }
Here's how it looks on a black background:

As you can see, this looks right. (OK, you need black not red, but the basic approach will be the same for any target color.)
EDIT 2015/1/21 . As noted in the comments on ar_j, the Prgba format requires premultiplication. In the example I gave, it's actually safe to ignore it, but if you changed the color channels in any way other than setting them to 0, you would need to multiply each value by (a/255) . For example, since aj_j shows for the channel G: pixels[i * 4 + 1] = (byte)(g * a / 255); Since g is zero in my code, this does not matter, but for non-primary colors you will need to do it this way.
Here, on a gradient fill background, it is simply shown that transparency works:

You can also write the modified version:
var enc = new PngBitmapEncoder(); enc.Frames.Add(BitmapFrame.Create(bmp)); using (Stream pngStream = File.OpenWrite(@"c:\temp\modified.png")) { enc.Save(pngStream); }
Here is the result:

You can see the red cross, and it will be on top of any background color used by StackOverflow. (White, as I write this, but maybe they will redesign one day.)
How much this will work for the images you want to use is harder to know for sure, because it depends on what your definition of βwhiteβ is - depending on how your images were created, you may find that everything is so small (especially around the edges), and you may need additional setup. But the basic approach should be in order.