GPH
GPH

Reputation: 1161

Flutter qrImage convert to Image

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,
),

Upvotes: 4

Views: 9858

Answers (3)

Ferran Buireu
Ferran Buireu

Reputation: 29320

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

Upvotes: 1

user3044484
user3044484

Reputation: 503

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;
  }
}

Upvotes: 8

Zroq
Zroq

Reputation: 8382

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();
       })
     ]));

}

Upvotes: 13

Related Questions