Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Rotate photo with SkiaSharp

Tags:

c#

.net

skiasharp

I'm trying to rotate photo with SkiaSharp to 90 degrees with following code:

    public SKBitmap Rotate()
    {
        var bitmap = SKBitmap.Decode("test.jpg");
        using (var surface = new SKCanvas(bitmap))
        {
            surface.RotateDegrees(90, bitmap.Width / 2, bitmap.Height / 2);
            surface.DrawBitmap(bitmap.Copy(), 0, 0);
        }

        return bitmap;
     }

But when I save bitmap to JPEG file, it has margins both on top and bottom of image.

Original image: http://imgur.com/pGAuko8. Rotated image: http://imgur.com/bYxpmI7.

What am I doing wrong?

like image 441
Dmitry Avatar asked Jul 13 '17 09:07

Dmitry


2 Answers

You may want to do something like this:

public static SKBitmap Rotate()
{
    using (var bitmap = SKBitmap.Decode("test.jpg"))
    {
        var rotated = new SKBitmap(bitmap.Height, bitmap.Width);

        using (var surface = new SKCanvas(rotated))
        {
            surface.Translate(rotated.Width, 0);
            surface.RotateDegrees(90);
            surface.DrawBitmap(bitmap, 0, 0);
        }

        return rotated;
    }
}

The reason for this (or yours not working as expected) is that you are rotating the bitmap on itself. You have basically taken an image, and then made a copy on draw it onto the first image. Thus, you still have the margins from the image below.

What I did was to create a NEW bitmap and then draw the decoded bitmap onto that.

The second "issue" is that you are rotating the image, but you are not changing the canvas dimensions. If the bitmap is 50x100, and then you rotate 90 degrees, the bitmap is now 100x50. As you can't actually change the dimensions of a bitmap once created, you have to create a new one. You can see this in the output image as it is actually cropped off a bit.

Hope this helps.

like image 153
Matthew Avatar answered Nov 06 '22 18:11

Matthew


Matthew's solution works for me too, but i had an issue when i tried to rotate bitmaps more than 90° or -90° (bitmap was drawed "out of display"). I highly recommend using this solution. Slightly modified result:

public static SKBitmap Rotate(SKBitmap bitmap, double angle)
    {
        double radians = Math.PI * angle / 180;
        float sine = (float)Math.Abs(Math.Sin(radians));
        float cosine = (float)Math.Abs(Math.Cos(radians));
        int originalWidth = bitmap.Width;
        int originalHeight = bitmap.Height;
        int rotatedWidth = (int)(cosine * originalWidth + sine * originalHeight);
        int rotatedHeight = (int)(cosine * originalHeight + sine * originalWidth);

        var rotatedBitmap = new SKBitmap(rotatedWidth, rotatedHeight);

        using (var surface = new SKCanvas(rotatedBitmap))
        {
            surface.Translate(rotatedWidth / 2, rotatedHeight / 2);
            surface.RotateDegrees((float)angle);
            surface.Translate(-originalWidth / 2, -originalHeight / 2);
            surface.DrawBitmap(bitmap, new SKPoint());
        }
        return rotatedBitmap;
    }

In my case I used this when I needed rotate picture on the Xamarin.iOS platform (who ever tried this, knows), works like a charm.

like image 29
Datch Avatar answered Nov 06 '22 20:11

Datch