Flutter qrImage convert to Image

4,342

Solution 1

Use a RepaintBoundary widget with a key to export the widget to a a b64 string which then you can export as an image.

Example:

Future<Uint8List> _getWidgetImage() async {
 try {
   RenderRepaintBoundary boundary =
      _renderObjectKey.currentContext.findRenderObject();
   ui.Image image = await boundary.toImage(pixelRatio: 3.0);
   ByteData byteData =
      await image.toByteData(format: ui.ImageByteFormat.png);
   var pngBytes = byteData.buffer.asUint8List();
   var bs64 = base64Encode(pngBytes);
   debugPrint(bs64.length.toString());
   return pngBytes;
 } catch (exception) {}

}

@override
Widget build(BuildContext context) {
    return Scaffold(
        body: Column(children: [
          RepaintBoundary(
            key: _renderObjectKey,
            child: QrImage(
            data: "some text",
            size: 300.0,
            version: 10,
            backgroundColor: Colors.white,
         ),
       ),
       RaisedButton(onPressed: () {
         _getWidgetImage();
       })
     ]));

}

Solution 2

Future<Uint8List> toQrImageData(String text) async {
  try {
    final image = await QrPainter(
      data: text,
      version: QrVersions.auto,
      gapless: false,
      color: hexToColor('#000000'),
      emptyColor: hexToColor('#ffffff'),
    ).toImage(300);
    final a = await image.toByteData(format: ImageByteFormat.png);
    return a.buffer.asUint8List();
  } catch (e) {
    throw e;
  }
}

Solution 3

A more updated typed answer, that adds responsibility seggregation and null-safety, extending the correct one from @Zroq would be:

  Future<Uint8List> createImageFromRenderKey({GlobalKey<State<StatefulWidget>>? renderKey}) async {
    try {
      final RenderRepaintBoundary boundary = renderKey?.currentContext?.findRenderObject()! as RenderRepaintBoundary;
      final ui.Image image = await boundary.toImage(pixelRatio: 3);
      final ByteData? byteData = await image.toByteData(format: ui.ImageByteFormat.png);

      return byteData!.buffer.asUint8List();
    } catch(_) {
      rethrow;
    }
  }

The idea is based on the same principle: using the global render key to create the ByteData that allows you to create the Uint8List buffer. However, the new versions of Flutter change the type of the boundary to become a RenderyObject? instead of a RenderRepaintBoundary.

The rethrow is (dirty) way of bypassing the limitation/small bug where RepaintBoundary may be being used in the UI to repaint the boundary (exposed as boundary.debugNeedsPaint), so it can potentially throw an unhandled exception or create a low-quality image buffer. So if the view is being used I rethrow the method. More details about the stack trace: https://github.com/theyakka/qr.flutter/issues/112

Share:
4,342
GPH
Author by

GPH

Updated on December 07, 2022

Comments

  • GPH
    GPH over 1 year

    I'm using qr_flutter to create QrImage. It's ok but I would like to convert QrImage into image in order to create a PDF file to print on the printer. Please kindly help!

    QrImage(
      data: qrString,
      size: 300.0,
      version: 10,
      backgroundColor: Colors.white,
    ),