# Overlay image with png 24

• ### Question

• I'm trying to create an overlay over a jpg image with a semi transparent png-24 but the output isn't what I want ;)
The out.png sure is semi transparent but the "base image" is completely overwritten so i guess that WritePixels isn't the correct method to use, can someone please point me in the right direction.

            const string IMAGE_BASE_PATH = "c:\\in.jpg";
const string IMAGE_OVERLAY_PATH = "c:\\overlay.png";
const string IMAGE_OUTPUT_PATH = "c:\\out.png";

BitmapImage baseImage;
BitmapImage overlayImage;

// read base image from disk
using (FileStream fs = new FileStream(IMAGE_BASE_PATH, FileMode.Open))
{
baseImage = new BitmapImage();
baseImage.BeginInit();
baseImage.StreamSource = fs;
baseImage.EndInit();
}

// read overlay image from disk
using (FileStream fs = new FileStream(IMAGE_OVERLAY_PATH, FileMode.Open))
{
overlayImage = new BitmapImage();
overlayImage.BeginInit();
overlayImage.StreamSource = fs;
overlayImage.EndInit();
}

// setup variables for base image
int widthBase = baseImage.PixelWidth;
int heightBase = baseImage.PixelHeight;
int bytesPerPixelBase = baseImage.Format.BitsPerPixel;
int strideBase = widthBase * bytesPerPixelBase;
byte[] bytesBase = new byte[heightBase * widthBase * bytesPerPixelBase];

// setup variables for overlay image
int widthOverlay = overlayImage.PixelWidth;
int heightOverlay = overlayImage.PixelHeight;
int bytesPerPixelOverlay = overlayImage.Format.BitsPerPixel;
int strideOverlay = widthOverlay * bytesPerPixelOverlay;
byte[] bytesOverlay = new byte[heightOverlay * widthOverlay * bytesPerPixelOverlay];

// bope copy pixels from base and overlay image
baseImage.CopyPixels(bytesBase, strideBase, 0);
overlayImage.CopyPixels(bytesOverlay, strideOverlay, 0);

// create new writable bitmap with the same
// properties as the overlay image
WriteableBitmap wb = new WriteableBitmap(widthBase, heightBase, 72, 72, System.Windows.Media.PixelFormats.Bgra32, null);

// write base image
wb.WritePixels(new Int32Rect(0, 0, widthBase, heightBase), bytesBase, strideBase, 0);

// write overlay image
wb.WritePixels(new Int32Rect(0, 0, widthOverlay, heightOverlay), bytesOverlay, strideOverlay, 0);

// get encoder from output filename
BitmapEncoder encoder = GetBitmapEncoder(GetMimeType(IMAGE_OUTPUT_PATH), 100);

// create frame from the writable bitmap and add to encoder

// write the new file back to disk
using (FileStream fs = new FileStream(IMAGE_OUTPUT_PATH, FileMode.Create))
{
encoder.Save(fs);
}
Thursday, September 10, 2009 7:12 PM

• Your WriteableBitmap code doesn't work because you aren't blending the two together. You're overwriting every pixel with the overlay image so your result is, not surprisingly, the overlay image. You'd need to loop through each pixel of both and do proper alpha blending.

Your second attempt is probably the easiest and fastest way to do this. You could RenderTargetBitmap with a pixel shader to do the blend, but all you want is a standard blend so why not let us do it for you :)
• Proposed as answer by Saturday, September 12, 2009 12:27 AM
• Marked as answer by Thursday, September 17, 2009 9:25 AM
Saturday, September 12, 2009 12:26 AM

### All replies

• Have you thought of using Pixel Shaders for this?
They were born for this kind of work.
Bigsby, Lisboa, Portugal - O que for, quando for, é que será o que é... http://bigsby.eu
Thursday, September 10, 2009 8:09 PM
• No i haven't... ;) Below is a working, but probably not the best, solution... Now, dig into Pixel Shaders!

            BitmapImage baseBitmap = new BitmapImage(new Uri(IMAGE_BASE_PATH));

Image baseImage = new Image() { Source = baseBitmap };
Image overlayImage = new Image() { Source = new BitmapImage(new Uri(IMAGE_OVERLAY_PATH)) };

Grid grid = new Grid();

grid.Arrange(new Rect(0, 0, baseBitmap.Width, baseBitmap.Height));

RenderTargetBitmap renderer = new RenderTargetBitmap(baseBitmap.PixelWidth,
baseBitmap.PixelHeight,
baseBitmap.DpiX,
baseBitmap.DpiY,
PixelFormats.Pbgra32);

renderer.Render(grid);

BitmapEncoder encoder = GetBitmapEncoder(GetMimeType(IMAGE_OUTPUT_PATH), 70);

using (FileStream fs = new FileStream(IMAGE_OUTPUT_PATH, FileMode.Create))
{
encoder.Save(fs);
}

• Edited by Thursday, September 10, 2009 9:23 PM Typo
Thursday, September 10, 2009 9:23 PM
• Your WriteableBitmap code doesn't work because you aren't blending the two together. You're overwriting every pixel with the overlay image so your result is, not surprisingly, the overlay image. You'd need to loop through each pixel of both and do proper alpha blending.

Your second attempt is probably the easiest and fastest way to do this. You could RenderTargetBitmap with a pixel shader to do the blend, but all you want is a standard blend so why not let us do it for you :)
• Proposed as answer by Saturday, September 12, 2009 12:27 AM
• Marked as answer by Thursday, September 17, 2009 9:25 AM
Saturday, September 12, 2009 12:26 AM