Skip to content

Instantly share code, notes, and snippets.

@kangabru
Last active November 9, 2020 13:27
Show Gist options
  • Star 4 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save kangabru/23770a466e9366f21ea8d12d22b6f12e to your computer and use it in GitHub Desktop.
Save kangabru/23770a466e9366f21ea8d12d22b6f12e to your computer and use it in GitHub Desktop.
Allows you extract an image of specific widgets within your app. Includes the ability to ignore certain widgets and to crop the final image.
import 'dart:typed_data';
import 'dart:ui' as ui;
import 'package:flutter/material.dart';
import 'package:flutter/rendering.dart';
// Note: [ui.Image] represents the lower level image data while [Image] represents a renderable image.
/// Provides the ability to take screenshots of specific widgets.
mixin Screenshot<T extends StatefulWidget> on State<T> {
static GlobalKey _key = new GlobalKey();
/// Wrap this around widget you wish to screenshot.
Widget screenshotThis(Widget child) => RepaintBoundary(key: _key, child: child);
/// Returns the screenshot of the widgets wrapped with [screenshotThis].
/// Applies an optional background and crop to the final image.
Future<ScreenshotData> takeScreenshot({Color background, Rect crop}) async {
var imageDataRaw = await _getScreenshotData();
var imageData = await _updateImage(imageDataRaw, background, crop);
return _convertDataToImage(imageData);
}
/// Returns the raw image of the widgets to screenshot.
Future<ui.Image> _getScreenshotData() async {
RenderRepaintBoundary boundary = _key.currentContext.findRenderObject();
return boundary.toImage();
}
/// Converts the raw image into a renderable form.
Future<ScreenshotData> _convertDataToImage(ui.Image imageData) async {
var byteData = await imageData.toByteData(format: ui.ImageByteFormat.png);
var pngBytes = byteData.buffer.asUint8List();
var image = Image.memory(pngBytes);
return ScreenshotData(image, pngBytes);
}
/// Processes an image with an optional background color and crop
Future<ui.Image> _updateImage(ui.Image image, [Color background, Rect crop]) {
var pictureRecorder = new ui.PictureRecorder();
Canvas canvas = new Canvas(pictureRecorder);
canvas.drawPaint(Paint()..color = background ?? Colors.transparent);
// No crop provided so render the full image
if (crop == null) {
int width = image.width, height = image.height;
canvas.drawImage(image, Offset.zero, Paint());
return pictureRecorder.endRecording().toImage(width, height);
}
// Crop the image by extracting the crop rect and moving to the top left
final width = crop.width, height = crop.height;
var dest = Rect.fromLTWH(0, 0, width, height);
canvas.drawImageRect(image, crop, dest, Paint());
return pictureRecorder.endRecording().toImage(width.floor(), height.floor());
}
}
/// Contains a renderable Image and the raw image bytes.
class ScreenshotData {
final Image image;
final Uint8List pngBytes;
ScreenshotData(this.image, this.pngBytes);
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment