Search code examples
wpfrotationbitmapsource

WPF Rotate and return BitmapSource by any angle


Hei, I tried this:

public static BitmapSource RotateImage(Image b, float angle)
    {
        BitmapSource rotita = (BitmapSource)b.Source;

        DrawingVisual drawingVisual = new DrawingVisual();

        using (DrawingContext drawingContext = drawingVisual.RenderOpen())
        {
            var transform = new RotateTransform(angle);
            drawingContext.PushTransform(transform);
            drawingContext.DrawImage(rotita, new Rect(0,0, rotita.PixelWidth, rotita.PixelHeight));
            drawingContext.Pop();
        }

        RenderTargetBitmap bmp = new RenderTargetBitmap(rotita.PixelWidth, rotita.PixelHeight, 96, 96, PixelFormats.Pbgra32);
        bmp.Render(drawingVisual);

        rotita = bmp;

        return rotita;
    }

But this does not work fine. I have this image at 0 degree and after rotation at 30 degrees this image.

What could I make the picture to be complete after rotation?

DrawingVisual drawingVisual = new DrawingVisual();            

        using (DrawingContext drawingContext = drawingVisual.RenderOpen())
        {
            drawingContext.DrawImage(back, new Rect(0, 0, imageWidth, imageHeight));            
            drawingContext.DrawImage(element, new Rect(x,y, elementWidth, elementHeight));
        }

        RenderTargetBitmap bmp = new RenderTargetBitmap(imageWidth, imageHeight, 96, 96, PixelFormats.Pbgra32);
        bmp.Render(drawingVisual);


        image.Source = bmp;

Element is the rotated image


Solution

  • The following method creates a composed bitmap from two others, where the second one is rotated around their common center point.

    The two crucial parts of this method are the calculation of the transformed bounds of the rotated bitmap, and the alignment of the two bitmaps at their common center point.

    private BitmapSource ComposeImage(
        BitmapSource image1, BitmapSource image2, double rotationAngle)
    {
        var rotation = new RotateTransform(rotationAngle);
        var size1 = new Size(image1.PixelWidth, image1.PixelHeight);
        var size2 = new Size(image2.PixelWidth, image2.PixelHeight);
        var center1 = new Vector(size1.Width / 2, size1.Height / 2);
        var center2 = new Vector(size2.Width / 2, size2.Height / 2);
        var rotatedSize = rotation.TransformBounds(new Rect(size2)).Size;
        var totalSize = new Size(
            Math.Max(size1.Width, rotatedSize.Width),
            Math.Max(size1.Height, rotatedSize.Height));
        var center = new Point(totalSize.Width / 2, totalSize.Height / 2);
    
        rotation.CenterX = center.X;
        rotation.CenterY = center.Y;
    
        var dv = new DrawingVisual();
    
        using (var dc = dv.RenderOpen())
        {
            dc.DrawImage(image1, new Rect(center - center1, size1));
            dc.PushTransform(rotation);
            dc.DrawImage(image2, new Rect(center - center2, size2));
        }
    
        var rtb = new RenderTargetBitmap(
            (int)totalSize.Width, (int)totalSize.Height, 96, 96, PixelFormats.Default);
        rtb.Render(dv);
    
        return rtb;
    }