flutter_svg icon indicating copy to clipboard operation
flutter_svg copied to clipboard

Images pixelated (CanvasKit)

Open KevMCarp opened this issue 3 years ago • 19 comments

When running on web using the canvaskit renderer images are pixelated. canvaskit canvaskit html html

void main() {
  runApp(const TestApp());
}

class TestApp extends StatelessWidget {
  const TestApp({Key? key}) : super(key: key);

  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      home: Scaffold(
        body: Center(
          child: SvgPicture.asset(
            'tick.svg',
            height: 100,
          ),
        ),
      ),
    );
  }
}

tick

KevMCarp avatar Feb 18 '22 20:02 KevMCarp

I also get the same issue using Flutter Web with canvaskit. Here is how the SVG is rendered: qd_web_rendering

And here is the SVG file: Qd

Code:

SizedBox(
  child: Align(
    alignment: Alignment.center,
    child: SvgPicture.asset(
      "assets/svgs/playing-cards/Qd.svg",
      width: 96,
    ),
  ),
),

philqc avatar Feb 19 '22 15:02 philqc

I'm seeing the same thing in my app: slightly aliasing when rendered in canvaskit.

jonbhanson avatar Apr 26 '22 13:04 jonbhanson

Same issue here with my brand logo. Unfortunately, I'll need to use a PNG instead since the loss of quality isn't worth the file size reduction.

Could this be related to https://github.com/flutter/flutter/issues/77485?

doppio avatar Jun 03 '22 19:06 doppio

Same thing is happening for me.

MarcAnProv avatar Jun 03 '22 19:06 MarcAnProv

Any progress of this problem?

dom3lek avatar Nov 09 '22 10:11 dom3lek

Same problem here 😢

LeonardoRosaa avatar May 19 '23 18:05 LeonardoRosaa

For CanvasKit - we use a supersampling technique that improves quality:

   Transform.scale(
      filterQuality: FilterQuality.medium,
      scale: 0.5,
      child: Transform.scale(
         scale: 2,
         child: SvgPicture(...),
      ),
   )

Keep in mind this is rendering the icon at 2X, so probably only suitable for smaller icons...

curt-weber avatar Jun 09 '23 18:06 curt-weber

For CanvasKit - we use a supersampling technique that improves quality:

   Transform.scale(
      filterQuality: FilterQuality.medium,
      scale: 0.5,
      child: Transform.scale(
         scale: 2,
         child: SvgPicture(...),
      ),
   )

Keep in mind this is rendering the icon at 2X, so probably only suitable for smaller icons...

Fixed for iOS, I had the same pixelated image for iOS devices, Flutter 3.12.0, now it is fixed, thanks a lot!

RobertApikyan avatar Jun 30 '23 09:06 RobertApikyan

@RobertApikyan I am confused. Is this issue fixed with the latest Flutter & flutter_svg or with the above workaround?

aytunch avatar Jun 30 '23 12:06 aytunch

@RobertApikyan I am confused. Is this issue fixed with the latest Flutter & flutter_svg or with the above workaround?

@aytunch the issue is fixed with the workaround.

RobertApikyan avatar Jul 01 '23 06:07 RobertApikyan

any updates on this? Still experiencing this issue on iOS. @curt-weber fix is working for some icons, however it is cutting of images, unless I specifically set height and width together Boxfit.contain.

blingkonnerth avatar Oct 11 '23 14:10 blingkonnerth

If the clipping is only happening on iOS, it could very likely be a bug related to Impeller. You should probably open a flutter issue showing a difference between skia/impeller. It's usually best to set a specific height and/or width so the icon has size (before it's fully loaded, or use placeholder). We found that was the cause of test flakes, attempting to tap an icon that has yet to be encountered (random test order) and thus having no size. cc @dnfield

curt-weber avatar Oct 11 '23 14:10 curt-weber

@curt-weber thanks for the super-sampling suggestion. In cases where the upscale causes partial rendering off-screen, the upscaled image is clipped before it's downscaled again resulting in effects like this:

(note the bottom grey icon is clipped because the pre-scaled (2x) version would bleed off-screen. I've put a red square behind the svg to demonstrate the region where the SVG should be) image

Is there a way to force flutter to render the entire widget even when the pixels aren't visible? Or another way to resolve this issue with super sampling?

Adam-Langley avatar Oct 23 '23 23:10 Adam-Langley

There is likely an ancestor widget that is adding clipping (such as a scrollview). You can't pop that clip using OverflowBox, but you could perform this same supersampling strategy using CustomPaint (or a custom RenderObject) since it doesn't add clipping until you ask it to. You could use PictureInfo to obtain a picture for drawing.

curt-weber avatar Oct 24 '23 15:10 curt-weber

I am running into the clipping issue too when using the transform on iOS. I will have to resort to using png's until this issue is fixed.

hunterwilhelm avatar Oct 30 '23 17:10 hunterwilhelm

Does this only reproduce on iOS(Impeller)? Testing with a parent clip (scrollview) doesn't reproduce on web (canvaskit) for me. FWIW this technique isn't needed for iOS and you could create a wrapper widget that performs the supersampling just on web, but passes through to the regular SvgPicture elsewhere. There is also a parameter clipViewbox that is available to the lower-level VectorGraphic but not exposed to SvgPicture - all you would have to do to test is switch to using VectorGraphic (clipViewbox=false) and report back your findings.

curt-weber avatar Oct 30 '23 21:10 curt-weber

Supersampling workaround doesn't seem to be working anymore on the new Flutter version (issue https://github.com/dnfield/flutter_svg/issues/1013).

Is there another way to solve this?

gabrielginter avatar Mar 14 '24 08:03 gabrielginter

This is captured within the flutter repo and you can follow for updates here: #139028

curt-weber avatar Mar 14 '24 14:03 curt-weber