Поверните фото с помощью SkiaSharp

Я пытаюсь повернуть фотографию с SkiaSharp на 90 градусов с помощью следующего кода:

    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;
     }

Но когда я сохраняю растровое изображение в файл JPEG, у него есть поля как сверху, так и снизу изображения.

Исходное изображение: https://imgur.com/pGAuko8. Повернутое изображение: https://imgur.com/bYxpmI7.

Что я делаю не так?


person Dmitry    schedule 13.07.2017    source источник
comment
github.com/mono/SkiaSharp/issues/836#issuecomment-489913279   -  person Nick Kovalsky    schedule 06.05.2021


Ответы (2)


Вы можете сделать что-то вроде этого:

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;
    }
}

Причина этого (или ваша не работает должным образом) заключается в том, что вы вращаете растровое изображение само по себе. Вы в основном взяли изображение, а затем сделали копию, нарисовав его на первом изображении. Таким образом, у вас все еще есть поля с изображения ниже.

Что я сделал, так это создал НОВОЕ растровое изображение, а затем нарисовал на нем декодированное растровое изображение.

Вторая «проблема» заключается в том, что вы вращаете изображение, но не меняете размеры холста. Если растровое изображение имеет размер 50x100, а затем вы поворачиваете его на 90 градусов, растровое изображение теперь имеет размер 100x50. Поскольку вы не можете изменить размеры уже созданного растрового изображения, вам необходимо создать новое. Вы можете видеть это на выходном изображении, так как оно немного обрезано.

Надеюсь это поможет.

person Matthew    schedule 14.07.2017

Решение Мэтью работает и для меня, но у меня возникла проблема, когда я попытался повернуть растровые изображения более чем на 90 ° или -90 ° (растровое изображение было нарисовано «вне экрана»). Я настоятельно рекомендую использовать этот решение. Слегка измененный результат:

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;
    }

В моем случае я использовал это, когда мне нужно было повернуть изображение на платформе Xamarin.iOS (кто когда-либо пробовал это, знает), работает как шарм.

person Datch    schedule 22.10.2019
comment
Убедитесь, что вы вызываете surface.Clear(), прежде чем начать вращение, иначе вы можете получить некоторые артефакты изображения. - person user2339814; 03.05.2020