Flutter qrImage 转换为 Image

4
我正在使用qr_flutter来创建QrImage。这很好,但我想把QrImage转换成图像以便创建PDF文件并在打印机上打印。请帮忙!
QrImage(
  data: qrString,
  size: 300.0,
  version: 10,
  backgroundColor: Colors.white,
),
3个回答

13

使用带有键的 RepaintBoundary 小部件将小部件导出为 b64 字符串,然后您可以将其导出为图像。

示例:

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

1
我正在写相同的答案,测试我的答案花了一点时间,你赢了!如果将来有时间,我会写另一个答案,尝试在插件中使用QrPainter类,并使用PictureRecorder类记录其画布结果。 - easeccy

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

1
一份更加更新的答案,增加了责任分离和空安全性,并扩展了@Zroq提供的正确答案,如下所示:
  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;
    }
  }

这个想法基于同样的原则:使用全局渲染键来创建ByteData,从而使您可以创建Uint8List缓冲区。然而,Flutter的新版本将边界的类型更改为RenderyObject?而不是RenderRepaintBoundaryrethrow是(肮脏的)绕过限制/小错误的方法,其中RepaintBoundary可能正在UI中用于重新绘制边界(作为boundary.debugNeedsPaint公开),因此它可能会抛出未处理的异常或创建低质量的图像缓冲区。所以如果视图正在使用,我会重新抛出该方法。 有关堆栈跟踪的更多详细信息:https://github.com/theyakka/qr.flutter/issues/112

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接