Answered by:
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.CacheOption = BitmapCacheOption.OnLoad; 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.CacheOption = BitmapCacheOption.OnLoad; 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 encoder.Frames.Add(BitmapFrame.Create(wb)); // 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
Answers
-
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 :)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.euThursday, 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.Children.Add(baseImage); grid.Children.Add(overlayImage); 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); encoder.Frames.Add(BitmapFrame.Create(renderer)); using (FileStream fs = new FileStream(IMAGE_OUTPUT_PATH, FileMode.Create)) { encoder.Save(fs); }
- Edited by olovnilzen 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 :)Saturday, September 12, 2009 12:26 AM