toImage method Null safety

Future<Image> toImage(
  1. {double pixelRatio = 1.0}
)

Capture an image of the current state of this render object and its children.

The returned ui.Image has uncompressed raw RGBA bytes in the dimensions of the render object, multiplied by the pixelRatio.

To use toImage, the render object must have gone through the paint phase (i.e. debugNeedsPaint must be false).

The pixelRatio describes the scale between the logical pixels and the size of the output image. It is independent of the dart:ui.FlutterView.devicePixelRatio for the device, so specifying 1.0 (the default) will give you a 1:1 mapping between logical pixels and the output pixels in the image.

The following is an example of how to go from a GlobalKey on a RepaintBoundary to a PNG:
class PngHome extends StatefulWidget {
  const PngHome({super.key});

  @override
  State<PngHome> createState() => _PngHomeState();
}

class _PngHomeState extends State<PngHome> {
  GlobalKey globalKey = GlobalKey();

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

  @override
  Widget build(BuildContext context) {
    return RepaintBoundary(
      key: globalKey,
      child: Center(
        child: TextButton(
          onPressed: _capturePng,
          child: const Text('Hello World', textDirection: TextDirection.ltr),
        ),
      ),
    );
  }
}

See also:

Implementation

Future<ui.Image> toImage({ double pixelRatio = 1.0 }) {
  assert(!debugNeedsPaint);
  final OffsetLayer offsetLayer = layer! as OffsetLayer;
  return offsetLayer.toImage(Offset.zero & size, pixelRatio: pixelRatio);
}