You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
{{ message }}
Repository navigation
Resizing via SKImage is blurry. Resizing via SKBitmap is great. #520
As @AndersMad discovered in #319 SKImage resizes very blurry, whereas resizing a SKBitmap works great.
Code
SKBitmap srcBitmap = ...
// Use attached "boat.jpg". A large image like this provides a more dramatic resize comparison
// (e.g. 5400x3615px). The more dramatic the resize, the more dramatic the resize quality between
// SKImage and SKBitmap.
int resizedWidth = 160, resizedHeight = 107;
// SKImage resizes blurry
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.DrawBitmap(srcBitmap, new SKRectI(0, 0, resizedWidth, resizedHeight),
paint);
surface.Canvas.Flush();
// save
using (var newImg = surface.Snapshot())
using (SKData data = newImg.Encode(SKEncodedImageFormat.Jpeg, 100))
using (Stream imgStream = data.AsStream())
{
// save the stream and look at the image. e.g. "blurry.jpg"
}
}
// SKBitmap resizes crisp.
SKImageInfo resizeInfo = new SKImageInfo(resizedWidth, resizedHeight);
using (SKBitmap resizedSKBitmap = srcBitmap.Resize(resizeInfo, SKBitmapResizeMethod.Lanczos3))
using (SKImage newImg = SKImage.FromPixels(resizedSKBitmap.PeekPixels()))
using (SKData data = newImg.Encode(SKEncodedImageFormat.Jpeg, jpegQuality))
using (Stream imgStream = data.AsStream())
{
// save the stream and look at the image. e.g. "crisp.jpg"
}
Expected Behavior
SKImage should be able to resize with the same good quality as SKBitmap
The ScalePixels takes SKFilterQuality - but the old SKPixmap.Resize could take SKBitmapResizeMethod.Lanczos3. In the new version Lanczos3 is converted to SKFilterQuality.Medium.
Lanczos3 is better imho, even compared to SKFilterQuality.High for smaller images / preserves sharpness (did a blind test with a few colleagues)..
Is there an alternative way than SKFilterQuality.High to bring back the better and sharper scaling of images like Lanczos3? Or maybe this is just how Skia rolls now .oO( making Chrome images scale with lower quality in the future ).
Look at face and dress (click on image to see org. to compare):
New SKFilterQuality.High:
Old SKBitmapResizeMethod.Lanczos3:
UPDATE!: I applied a small sharpening filter (SKImageFilter) and now down-scaled images is actually better than before - maybe in a "cheat" way(?)..
New with sharpen filter:
Reacted by dsyno, CShepartd, Oleg M and Mehmet Akif DERE
Thanks @AndersMad for testing this. So with your updated comment, what combination are you using now?... SKFilterQuality.High plus the sharpening filter?
P.S. Please include the code you're using for the "sharpening filter". Perhaps it only became available in v1.68 because I don't see it available anywhere.
@dsyno before i used ScalePixels with some mem overhead when the image needed to scale and crop.. But now I create a canvas and do a DrawBitmap on that - think this has less overhead when dealing with offsets and cropping etc. First mode was crisp before update - and the last mode was not usable as it was very blurry. After update they where both semi blurry :/ win some lose some.. Overall the performance is noticeable better though.
Now I i do a SKImageFilter.CreateMatrixConvolution with a tiny bit of sharpening before the draw - and it does seem to work nicely when scaling big to small.
So for now I have this (hope this "hacky cheat mode" helps):
Wow. Bummer all that has to be done @AndersMad, instead of Skia resize just working properly.
It doesn't seem this was fixed properly afterall, @mattleibow. It appears it still resizes blurry and hoops have to be jumped through to get a good resize.
NOTE: It is less blurry than before - it's just missing some "crispyness" - and my cheat way actually scored higher in the blind test.
I believe its 100% the Skia and has nothing to do with SkiaSharp. My guess is - that if you use GPU/OpenGL it will be crispy - its the software scaling that's off. As Skia is primarily used for Chrome canvas - GPU rendering is the focus as almost all browsers/devices has that - and software part just a bloater (again, just me guessing). Not using Lanczos3 might be the thing that makes it faster.
I have been following along and I believe that @AndersMad is probably using the resize idea as it was actually designed. SkiaSharp (and skia) is primarily a drawing API, not an image processor, and as such, they have split concepts into separate steps.
If you are using an image processing library, this is typically the case where things are batched or single-run. And, you often provide some image, perform a task (such as resize), and then output the best quality.
With SkiaSharp, you are actually going to be working with a different idea. You start with nothing and then draw what you want as fast as possible, with good-enough quality. Since this is meant for drawing a UI, chances are the user won't notice any minor flaws (as can be seen in the general improvement for the basic bitmap resize).
However!
SkiaSharp does not leave you there and provides a series of filters, shaders and effects to help provide an even better image. And this is where I think @AndersMad comes in. The base resize will always be faster that the previous version because that is what it is designed to do - be fast. But, the user code will pull together the various features and make it the best as possible.
I don't think that SkiaSharp will ever provide all the little operations to get the best image, as this is more for additional libraries or frameworks. Think of SkiaSharp as the core drawing engine - it does the steps as fast as possible, but leaves the actual big chunks to libraries.
Reacted by Anders Madsen, Uwe Keim and Matteo Gazzoni
With regards to an additional library, I have been trying to collect together a few useful APIs that provide an additional layer of usefulness to SkiaSharp. Right now, there is just a few extra geometry and a basic path interpolation: https://github.com/mono/SkiaSharp.Extended/tree/master/SkiaSharp.Extended
But, I hope to slowly add features here to make things useful. One example would be a set of extension methods that could take the basic Resize method and turn it into a real, high-quality process. Or even a new type that can be much more useful.
If this really is an issue that needs solving within the library, please open an issue there and share code and PRs. As that is a satellite library, it is much, much easier to work with as it just depends on a NuGet.
@AndersMad please include the c# code you used... aka in ur update u say you applied SKImageFilter could you include code sample so i can see what u did
Activity
mattleibow commentedon Nov 29, 2018
As of v1.68, this is not a problem anymore. Google has improved the resize APIs and consolidated them into the
SKPixmap.ScalePixels.Then, we added more members to the 3 imaging types (
SKPixmap,SKImage,SKBitmap) to be consistent:ScalePixelsscales the current pixels and puts the result into the provided container - typically aSKPixmapResizescales the current and returns them in the container that resized them - right now, just forSKBitmapAndersMad commentedon Dec 6, 2018
Q & FYI for others who scale:
The
ScalePixelstakesSKFilterQuality- but the oldSKPixmap.Resizecould takeSKBitmapResizeMethod.Lanczos3. In the new version Lanczos3 is converted toSKFilterQuality.Medium.Lanczos3is better imho, even compared toSKFilterQuality.Highfor smaller images / preserves sharpness (did a blind test with a few colleagues)..Is there an alternative way than
SKFilterQuality.Highto bring back the better and sharper scaling of images likeLanczos3? Or maybe this is just how Skia rolls now .oO( making Chrome images scale with lower quality in the future ).Look at face and dress (click on image to see org. to compare):
New

SKFilterQuality.High:Old

SKBitmapResizeMethod.Lanczos3:UPDATE!: I applied a small sharpening filter (
SKImageFilter) and now down-scaled images is actually better than before - maybe in a "cheat" way(?)..New with sharpen filter:

dsyno commentedon Dec 6, 2018
Thanks @AndersMad for testing this. So with your updated comment, what combination are you using now?...
SKFilterQuality.Highplus the sharpening filter?P.S. Please include the code you're using for the "sharpening filter". Perhaps it only became available in v1.68 because I don't see it available anywhere.
AndersMad commentedon Dec 6, 2018
@dsyno before i used
ScalePixelswith some mem overhead when the image needed to scale and crop.. But now I create a canvas and do aDrawBitmapon that - think this has less overhead when dealing with offsets and cropping etc. First mode was crisp before update - and the last mode was not usable as it was very blurry. After update they where both semi blurry :/ win some lose some.. Overall the performance is noticeable better though.Now I i do a
SKImageFilter.CreateMatrixConvolutionwith a tiny bit of sharpening before the draw - and it does seem to work nicely when scaling big to small.So for now I have this (hope this "hacky cheat mode" helps):
dsyno commentedon Dec 6, 2018
Wow. Bummer all that has to be done @AndersMad, instead of Skia resize just working properly.
It doesn't seem this was fixed properly afterall, @mattleibow. It appears it still resizes blurry and hoops have to be jumped through to get a good resize.
AndersMad commentedon Dec 7, 2018
NOTE: It is less blurry than before - it's just missing some "crispyness" - and my cheat way actually scored higher in the blind test.
I believe its 100% the Skia and has nothing to do with SkiaSharp. My guess is - that if you use GPU/OpenGL it will be crispy - its the software scaling that's off. As Skia is primarily used for Chrome canvas - GPU rendering is the focus as almost all browsers/devices has that - and software part just a bloater (again, just me guessing). Not using Lanczos3 might be the thing that makes it faster.
mattleibow commentedon Dec 7, 2018
I have been following along and I believe that @AndersMad is probably using the resize idea as it was actually designed. SkiaSharp (and skia) is primarily a drawing API, not an image processor, and as such, they have split concepts into separate steps.
If you are using an image processing library, this is typically the case where things are batched or single-run. And, you often provide some image, perform a task (such as resize), and then output the best quality.
With SkiaSharp, you are actually going to be working with a different idea. You start with nothing and then draw what you want as fast as possible, with good-enough quality. Since this is meant for drawing a UI, chances are the user won't notice any minor flaws (as can be seen in the general improvement for the basic bitmap resize).
However!
SkiaSharp does not leave you there and provides a series of filters, shaders and effects to help provide an even better image. And this is where I think @AndersMad comes in. The base resize will always be faster that the previous version because that is what it is designed to do - be fast. But, the user code will pull together the various features and make it the best as possible.
I don't think that SkiaSharp will ever provide all the little operations to get the best image, as this is more for additional libraries or frameworks. Think of SkiaSharp as the core drawing engine - it does the steps as fast as possible, but leaves the actual big chunks to libraries.
mattleibow commentedon Dec 7, 2018
With regards to an additional library, I have been trying to collect together a few useful APIs that provide an additional layer of usefulness to SkiaSharp. Right now, there is just a few extra geometry and a basic path interpolation: https://github.com/mono/SkiaSharp.Extended/tree/master/SkiaSharp.Extended
But, I hope to slowly add features here to make things useful. One example would be a set of extension methods that could take the basic
Resizemethod and turn it into a real, high-quality process. Or even a new type that can be much more useful.If this really is an issue that needs solving within the library, please open an issue there and share code and PRs. As that is a satellite library, it is much, much easier to work with as it just depends on a NuGet.
https://github.com/mono/SkiaSharp.Extended
mattleibow commentedon Dec 7, 2018
If you create an issue in the extended repo, just link back to this so we have some code to start with and can initiate a discussion.
AndersMad commentedon Dec 10, 2018
This might be related: "Anti-aliasing change between m65 and m69" https://groups.google.com/forum/#!topic/skia-discuss/QrJadRQR5A4 - only for CPU
Seabizkit commentedon Oct 13, 2021
@AndersMad please include the c# code you used... aka in ur update u say you applied SKImageFilter could you include code sample so i can see what u did
Seabizkit commentedon Jan 26, 2022
@AndersMad could u please had the full code! so we can see how this is done.