Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

RenderRepaintBoundary.toImage bad quality #21269

Closed
luohaohaha opened this issue Aug 31, 2018 · 10 comments
Closed

RenderRepaintBoundary.toImage bad quality #21269

luohaohaha opened this issue Aug 31, 2018 · 10 comments
Labels
engine flutter/engine repository. See also e: labels. P2 Important issues not at the top of the work list

Comments

@luohaohaha
Copy link

luohaohaha commented Aug 31, 2018

The method of my screenshot is like this, but the screenshots I got are of poor quality. What went wrong?

Future<void> _capturePng() async {
    RenderRepaintBoundary boundary = globalKey.currentContext.findRenderObject();
    ui.Image image = await boundary.toImage();
    ByteData byteData = await image.toByteData(format: ui.ImageByteFormat.png);
    setState(() {
      bytes = byteData.buffer.asUint8List();
    });
//    print(pngBytes);
  }

The widget
screenshot_20180831-165848

The screenshot
screenshot_20180831-165912

flutter doctor

Doctor summary (to see all details, run flutter doctor -v):
[✓] Flutter (Channel dev, v0.5.7, on Linux, locale zh_CN.UTF-8)
[!] Android toolchain - develop for Android devices (Android SDK 28.0.2)
    ! Some Android licenses not accepted.  To resolve this, run: flutter doctor --android-licenses
[✓] Android Studio (version 3.0)
    ✗ Flutter plugin not installed; this adds Flutter specific functionality.
    ✗ Dart plugin not installed; this adds Dart specific functionality.
[✓] Android Studio (version 3.2)
    ✗ Flutter plugin not installed; this adds Flutter specific functionality.
    ✗ Dart plugin not installed; this adds Dart specific functionality.
[✓] Connected devices (1 available)

! Doctor found issues in 1 category.
@zoechi
Copy link
Contributor

zoechi commented Aug 31, 2018

Can you please try in a newer Flutter version like the newest beta?

@zoechi zoechi added waiting for customer response The Flutter team cannot make further progress on this issue until the original reporter responds engine flutter/engine repository. See also e: labels. labels Aug 31, 2018
@bigship
Copy link

bigship commented Aug 31, 2018

Same issue here. The screenshot got pixelated.

Doctor summary (to see all details, run flutter doctor -v):
[✓] Flutter (Channel beta, v0.6.0, on Mac OS X 10.13.6 17G65, locale zh-Hans-CN)
[✓] Android toolchain - develop for Android devices (Android SDK 27.0.2)
[✓] iOS toolchain - develop for iOS devices (Xcode 9.4.1)
[✓] Android Studio (version 3.1)
[✓] IntelliJ IDEA Ultimate Edition (version 2017.3.2)
[✓] VS Code (version 1.25.1)
[✓] Connected devices (2 available)

• No issues found!

@zoechi zoechi added this to the Goals milestone Aug 31, 2018
@luohaohaha
Copy link
Author

luohaohaha commented Sep 21, 2018

@zoechi
A new issue
The image in the screenshot is missing.
before
screenshot_20180921-115417
after
screenshot_20180921-115424

doctor

Doctor summary (to see all details, run flutter doctor -v):
[✓] Flutter (Channel dev, v0.9.1, on Linux, locale zh_CN.UTF-8)
[!] Android toolchain - develop for Android devices (Android SDK 28.0.2)
    ! Some Android licenses not accepted.  To resolve this, run: flutter doctor --android-licenses
[✓] Android Studio (version 3.0)
    ✗ Flutter plugin not installed; this adds Flutter specific functionality.
    ✗ Dart plugin not installed; this adds Dart specific functionality.
[✓] Android Studio (version 3.2)
    ✗ Flutter plugin not installed; this adds Flutter specific functionality.
    ✗ Dart plugin not installed; this adds Dart specific functionality.
[✓] Connected devices (1 available)

! Doctor found issues in 1 category.

@no-response no-response bot removed the waiting for customer response The Flutter team cannot make further progress on this issue until the original reporter responds label Sep 21, 2018
@teejar
Copy link

teejar commented Nov 20, 2018

The original issue here is easily fixed when using pixelratio to capture a bigger image.

As for the second issue.
I had the same issues when capturing images from repaintboundary with boundary.toImage() method. Most of the times any images inside the boundary did not show in the captured png.

But this issue seems to have been fixed recently. I've tested this with the newest version of flutter with multiple devices and the capture has not failed.

@fujingjunben
Copy link

Picture.toImage() will generate bad quality too.

  Future<ui.Image> _clipImage(ui.Image originImage, Offset blockCenter,
      Size canvasSize, Size blockSize) async {
    DefaultCaptchaStrategy strategy = DefaultCaptchaStrategy();
    Path blockShape = strategy.getBlockShape(blockCenter, blockSize);
    ui.PictureRecorder recorder = ui.PictureRecorder();
    Canvas canvas = Canvas(
        recorder, Rect.fromLTWH(0, 0, canvasSize.width, canvasSize.height));
    canvas.translate(
        blockSize.width - blockCenter.dx, blockSize.height - blockCenter.dy);

    canvas.clipPath(blockShape);

    ImageUtil.paintImage(
        originImage, Offset.zero & canvasSize, canvas, Paint(), BoxFit.fill);
    Paint paint = Paint()
      ..color = Colors.red
      ..style = PaintingStyle.stroke
      ..strokeWidth = 3;

    canvas.drawPath(blockShape, paint);

    ui.Picture picture = recorder.endRecording();

    double imageWidth = blockSize.width * 2;
    double imageHeight = blockSize.height * 2;
    final pngBytes = await picture
        .toImage(imageWidth.ceil(), imageHeight.ceil())
        .toByteData(format: ui.ImageByteFormat.png);

    var codec = await ui.instantiateImageCodec(pngBytes.buffer.asUint8List());
    var frame = await codec.getNextFrame();
    return frame.image;
  }

l 20 as 5pip n flkp 8

@Hakim-Allaoui
Copy link

Hakim-Allaoui commented Mar 11, 2020

Increase pixelRatio should improve the image quality
ui.Image image = await boundary.toImage(pixelRatio: 2.0);

@kf6gpe kf6gpe added the P2 Important issues not at the top of the work list label May 29, 2020
@udhayak4251
Copy link

Increase pixelRatio should improve the image quality
ui.Image image = await boundary.toImage(pixelRatio: 2.0);

Thank You.. Works fine

@Hixie Hixie removed this from the None. milestone Aug 17, 2020
@markusaksli-nc
Copy link
Member

markusaksli-nc commented Oct 27, 2020

This is working as expected on the lastes master 1.24.0-4.0.pre.81.

flutter doctor -v
[√] Flutter (Channel master, 1.24.0-4.0.pre.81, on Microsoft Windows [Version 10.0.19041.572], locale en-US)
    • Flutter version 1.24.0-4.0.pre.81 at C:\Development\flutter_master
    • Framework revision 05ab0eba19 (11 hours ago), 2020-10-26 19:22:25 -0700
    • Engine revision 1857470267
    • Dart version 2.11.0 (build 2.11.0-260.0.dev)

[√] Android toolchain - develop for Android devices (Android SDK version 30.0.2)
    • Android SDK at C:\Users\marku\AppData\Local\Android\sdk
    • Platform android-30, build-tools 30.0.2
    • Java binary at: C:\Users\marku\AppData\Local\JetBrains\Toolbox\apps\AndroidStudio\ch-0\201.6858069\jre\bin\java
    • Java version OpenJDK Runtime Environment (build 1.8.0_242-release-1644-b01)
    • All Android licenses accepted.

[√] Chrome - develop for the web
    • Chrome at C:\Program Files (x86)\Google\Chrome\Application\chrome.exe

[√] Visual Studio - develop for Windows (Visual Studio Community 2019 16.6.5)
    • Visual Studio at C:\Program Files (x86)\Microsoft Visual Studio\2019\Community
    • Visual Studio Community 2019 version 16.6.30320.27
    • Windows 10 SDK version 10.0.18362.0

[√] Android Studio (version 4.1.0)
    • Android Studio at C:\Users\marku\AppData\Local\JetBrains\Toolbox\apps\AndroidStudio\ch-0\201.6858069
    • Flutter plugin can be installed from:
       https://plugins.jetbrains.com/plugin/9212-flutter
    • Dart plugin can be installed from:
       https://plugins.jetbrains.com/plugin/6351-dart
    • Java version OpenJDK Runtime Environment (build 1.8.0_242-release-1644-b01)

[√] IntelliJ IDEA Ultimate Edition (version 2020.3)
    • IntelliJ at C:\Users\marku\AppData\Local\JetBrains\Toolbox\apps\IDEA-U\ch-0\203.5251.39
    • Flutter plugin can be installed from:
       https://plugins.jetbrains.com/plugin/9212-flutter
    • Dart plugin can be installed from:
       https://plugins.jetbrains.com/plugin/6351-dart

[√] Connected device (6 available)
    • SM G950F (mobile)           • ce12171c51cc001c03 • android-arm64  • Android 9 (API 28)
    • sdk gphone x86 arm (mobile) • emulator-5554      • android-x86    • Android 11 (API 30) (emulator)
    • Windows (desktop)           • windows            • windows-x64    • Microsoft Windows [Version 10.0.19041.572]
    • Web Server (web)            • web-server         • web-javascript • Flutter Tools
    • Chrome (web)                • chrome             • web-javascript • Google Chrome 86.0.4240.111
    • Edge (web)                  • edge               • web-javascript • Microsoft Edge 86.0.622.38

• No issues found!

Here is a sample to play around with pixelRatio.

Complete code sample
import 'dart:typed_data';
import 'dart:ui' as ui;

import 'package:flutter/material.dart';
import 'package:flutter/rendering.dart';

void main() => runApp(MyApp());

class MyApp extends StatefulWidget {
  @override
  _MyAppState createState() => _MyAppState();
}

class _MyAppState extends State<MyApp> {
  var globalKey = GlobalKey();
  Uint8List bytes;
  BuildContext localContext;

  double ratio = 1.0;
  
  @override
  Widget build(BuildContext context) {
    return RepaintBoundary(
      key: globalKey,
      child: MaterialApp(
        title: 'Sample',
        home: Builder(
          builder: (ctx) {
            localContext = ctx;
            return Scaffold(
              appBar: AppBar(
                title: const Text("Logical pixels vs image size"),
              ),
              body: Center(
                child: GestureDetector(
                  onTap: () async {
                    await _capturePng();
                    Navigator.push(
                      localContext,
                      MaterialPageRoute(
                        builder: (BuildContext context) {
                          Image image = Image.memory(bytes);
                          image.image.resolve(new ImageConfiguration()).addListener(
                                new ImageStreamListener(
                                  (ImageInfo imgInf, _) => print("Created screenshot with resolution ${imgInf.image.width}x${imgInf.image.height}"),
                                ),
                              );
                          return Stack(
                            children: [
                              image,
                              Container(
                                padding: EdgeInsets.all(3.0),
                                decoration: BoxDecoration(
                                  border: Border.all(
                                    color: Colors.green,
                                    width: 3.0,
                                  ),
                                ),
                              ),
                            ],
                          );
                        },
                      ),
                    );
                  },
                  child: Container(
                    width: 300,
                    height: 300,
                    color: Colors.orange,
                    alignment: Alignment.center,
                    child: const Text("Tap to screenshot!"),
                  ),
                ),
              ),
              bottomNavigationBar: Container(
                height: 100,
                child: Card(
                  child: Column(
                    children: [
                      Row(
                        children: [
                          Flexible(
                            child: Slider(
                              value: ratio,
                              min: 1.0,
                              max: 8.0,
                              onChanged: (value) {
                                setState(() => ratio = value);
                              },
                            ),
                          ),
                          RaisedButton(
                            child: const Text("Use device\npixel ratio", textAlign: TextAlign.center),
                            onPressed: () => setState(() => ratio = ui.window.devicePixelRatio),
                          ),
                        ],
                      ),
                      Text("pixelRatio: ${ratio.toStringAsFixed(2)}"),
                      Text("Screenshot resolution: ${getScreenshotRes()}")
                    ],
                  ),
                ),
              ),
            );
          },
        ),
      ),
    );
  }

  String getScreenshotRes() {
    var size = MediaQuery.of(localContext).size;
    return "${(size.width * ratio).ceil()}x${(size.height * ratio).ceil()}";
  }

  Future<void> _capturePng() async {
    RenderRepaintBoundary boundary = globalKey.currentContext.findRenderObject();
    ui.Image image = await boundary.toImage(pixelRatio: ratio);
    ByteData byteData = await image.toByteData(format: ui.ImageByteFormat.png);
    setState(() => bytes = byteData.buffer.asUint8List());
  }
}

To understand the difference between logical and physical pixels see devicePixelRatio.

@hovanhung98hust
Copy link

Increase pixelRatio should improve the image quality
ui.Image image = await boundary.toImage(pixelRatio: 2.0);

this work for me, thanks

@github-actions
Copy link

github-actions bot commented Aug 9, 2021

This thread has been automatically locked since there has not been any recent activity after it was closed. If you are still experiencing a similar issue, please open a new bug, including the output of flutter doctor -v and a minimal reproduction of the issue.

@github-actions github-actions bot locked as resolved and limited conversation to collaborators Aug 9, 2021
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
engine flutter/engine repository. See also e: labels. P2 Important issues not at the top of the work list
Projects
None yet
Development

No branches or pull requests