Merge png images into single image in WPF
Asked Answered
I

1

7

I'm looking for a way to Merge some PNG tile images into a big image. So I search and found some links. This is not answered properly. This is not tiling, it's good for overlaying images and this is not using WPF. So I'm making this question.

Problem Definition:

I have 4 PNG images. I want to merge them into a single PNG image, like this

-------------------
|        |        |
|  png1  |  png2  |
|        |        |
-------------------
|        |        |
|  png3  |  png4  |
|        |        |
-------------------

Question:

What is the best and efficient way of doing this (The resulting image must be PNG)?

Islas answered 2/2, 2013 at 12:30 Comment(1)
The joining is a separate problem to the saving. Once you have the joined bitmap you can save it in any supported format.Follicle
E
18
// Loads the images to tile (no need to specify PngBitmapDecoder, the correct decoder is automatically selected)
BitmapFrame frame1 = BitmapDecoder.Create(new Uri(path1), BitmapCreateOptions.None, BitmapCacheOption.OnLoad).Frames.First();
BitmapFrame frame2 = BitmapDecoder.Create(new Uri(path2), BitmapCreateOptions.None, BitmapCacheOption.OnLoad).Frames.First();
BitmapFrame frame3 = BitmapDecoder.Create(new Uri(path3), BitmapCreateOptions.None, BitmapCacheOption.OnLoad).Frames.First();
BitmapFrame frame4 = BitmapDecoder.Create(new Uri(path4), BitmapCreateOptions.None, BitmapCacheOption.OnLoad).Frames.First();

// Gets the size of the images (I assume each image has the same size)
int imageWidth = frame1.PixelWidth;
int imageHeight = frame1.PixelHeight;

// Draws the images into a DrawingVisual component
DrawingVisual drawingVisual = new DrawingVisual();
using (DrawingContext drawingContext = drawingVisual.RenderOpen())
{
    drawingContext.DrawImage(frame1, new Rect(0, 0, imageWidth, imageHeight));
    drawingContext.DrawImage(frame2, new Rect(imageWidth, 0, imageWidth, imageHeight));
    drawingContext.DrawImage(frame3, new Rect(0, imageHeight, imageWidth, imageHeight));
    drawingContext.DrawImage(frame4, new Rect(imageWidth, imageHeight, imageWidth, imageHeight));
}

// Converts the Visual (DrawingVisual) into a BitmapSource
RenderTargetBitmap bmp = new RenderTargetBitmap(imageWidth * 2, imageHeight * 2, 96, 96, PixelFormats.Pbgra32);
bmp.Render(drawingVisual);

// Creates a PngBitmapEncoder and adds the BitmapSource to the frames of the encoder
PngBitmapEncoder encoder = new PngBitmapEncoder();
encoder.Frames.Add(BitmapFrame.Create(bmp));

// Saves the image into a file using the encoder
using (Stream stream = File.Create(pathTileImage))
    encoder.Save(stream);
Erelong answered 2/2, 2013 at 12:38 Comment(6)
@HosseinNarimaniRad I've decided to use another method. Using WPF!Expire
@HosseinNarimaniRad I've added comments in the code (no need to specify PngBitmapDecoder, the correct decoder is automatically selected)Expire
@HosseinNarimaniRad I've replaced File.OpenWrite by File.Create at the end of the code.Expire
Does it make any great difference?Islas
By the way using this method when I merge 4 30k-PNG images, the resulting image would be 500kb. Is it usual?Islas
@HosseinNarimaniRad If the file already exists OpenWrite will just replace the content it writes with the new bytes (if the previous file is 500KB and only 200KB is written by the stream, the file will still be 500KB). Create removes the content of the previous file then add the new content.Expire

© 2022 - 2024 — McMap. All rights reserved.