Search code examples
c#wpfbitmapimagetiling

Create a Composite BitmapImage in WPF


I have three BitmapImages that I would like to stitch together to create a composite image. The three images to be stitched together are aligned in the following way:

The images are of a type System.Windows.Media.Imaging.BitmapImage. I have looked at the following solution, but it uses System.Drawing.Graphics to perform stitching. I find it unintuitive to convert my BitmapImage to System.Drawing.Bitmap everytime I want to stich them together.

Is there a simple way to stitch three images of type System.Windows.Media.Imaging.BitmapImage together?


Solution

  • In addition to the options described in the other answer, the code below stitches three BitmapSource together into a single WriteableBitmap:

    public BitmapSource StitchBitmaps(BitmapSource b1, BitmapSource b2, BitmapSource b3)
    {
        if (b1.Format != b2.Format || b1.Format != b3.Format)
        {
            throw new ArgumentException("All input bitmaps must have the same pixel format");
        }
    
        var width = Math.Max(b1.PixelWidth, b2.PixelWidth + b3.PixelWidth);
        var height = b1.PixelHeight + Math.Max(b2.PixelHeight, b3.PixelHeight);
        var wb = new WriteableBitmap(width, height, 96, 96, b1.Format, null);
        var stride1 = (b1.PixelWidth * b1.Format.BitsPerPixel + 7) / 8;
        var stride2 = (b2.PixelWidth * b2.Format.BitsPerPixel + 7) / 8;
        var stride3 = (b3.PixelWidth * b3.Format.BitsPerPixel + 7) / 8;
        var size = b1.PixelHeight * stride1;
        size = Math.Max(size, b2.PixelHeight * stride2);
        size = Math.Max(size, b3.PixelHeight * stride3);
    
        var buffer = new byte[size];
        b1.CopyPixels(buffer, stride1, 0);
        wb.WritePixels(
            new Int32Rect(0, 0, b1.PixelWidth, b1.PixelHeight),
            buffer, stride1, 0);
    
        b2.CopyPixels(buffer, stride2, 0);
        wb.WritePixels(
            new Int32Rect(0, b1.PixelHeight, b2.PixelWidth, b2.PixelHeight),
            buffer, stride2, 0);
    
        b3.CopyPixels(buffer, stride3, 0);
        wb.WritePixels(
            new Int32Rect(b2.PixelWidth, b1.PixelHeight, b3.PixelWidth, b3.PixelHeight),
            buffer, stride3, 0);
    
        return wb;
    }