Fastest way to scale an SKImage (SkiaSharp)
Asked Answered
S

1

7

I'm looking for the fastest way to resize an SKImage. Unfortunately I found a few examples.

I ask this because if I perform these functions in parallel (in my case about 60 threads) the execution time of each single scaling function increases up to twenty times as much.

I tried with the following methods and the performance looks very similar, is there anything better?

Method 1:

SKImage src = (...);
SKImageInfo info = new SKImageInfo(width, height, SKColorType.Bgra8888);
SKImage output = SKImage.Create(info);
src.ScalePixels(output.PeekPixels(), SKFilterQuality.None);

Method 2:

SKImage src = (...);
SKImage output;
float resizeFactorX = (float)width / (float)Src.Width;
float resizeFactorY = (float)height / (float)Src.Height;

using (SKSurface surface = SKSurface.Create((int)(Src.Width * 
       resizeFactorX), (int)(Src.Height * resizeFactorY),
       SKColorType.Bgra8888, SKAlphaType.Opaque))
{
  surface.Canvas.SetMatrix(SKMatrix.MakeScale(resizeFactorX, resizeFactorY));
  surface.Canvas.DrawImage(Src, 0, 0);
  surface.Canvas.Flush();
  output = surface.Snapshot();
}
Scorch answered 24/1, 2018 at 12:38 Comment(0)
F
5

This is the code I use. An additional thought is to be sure to wrap your SKImage objects in using, to ensure they're disposed of quickly. I'm not sure if that could be causing the slowdown with each iteration.

using (var surface = SKSurface.Create(resizedWidth, resizedHeight,
    SKImageInfo.PlatformColorType, SKAlphaType.Premul))
using (var paint = new SKPaint())
{
    // high quality with antialiasing
    paint.IsAntialias = true;
    paint.FilterQuality = SKFilterQuality.High;

    // draw the bitmap to fill the surface
    surface.Canvas.DrawImage(srcImg, new SKRectI(0, 0, resizedWidth, resizedHeight),
        paint);
    surface.Canvas.Flush();

    using (var newImg = surface.Snapshot())
    {
        // do something with newImg
    }
}
Felicitation answered 15/5, 2018 at 7:23 Comment(2)
The SKSurface.Create overload obsolete and will generate a warning. The modern code is SKSurface.Create(new SKImageInfo { Width = resizedWidth, Height = resizedHeight, ColorType = SKImageInfo.PlatformColorType, AlphaType = SKAlphaType.Premul })Sandy
I tested this vs the current SKBitMap.Resize and it seems now that they produce identical results so no need for the Canvas anymore or most of this codeIntercalary

© 2022 - 2024 — McMap. All rights reserved.