Flutter中如何在保存文件前缩小原始RGBA格式的屏幕截图数据?
解决Flutter录屏中高DPR图像缩容为原始尺寸的RGBA数据方案
要在保留原始RGBA格式的前提下,将高DPR捕获的屏幕图像缩回到原始逻辑尺寸以减小数据大小,可通过Flutter的Canvas直接操作图像绘制实现,全程无需编码为PNG,性能损耗极低。
实现步骤
- 捕获高DPR图像后,获取Widget的原始逻辑尺寸(即
boundary.size) - 使用
PictureRecorder和Canvas将高DPR图像缩放到目标尺寸绘制 - 从Recorder生成缩放后的图像,提取RGBA字节数据
- 及时释放图像资源避免内存泄漏
完整代码示例
import 'dart:ui' as ui; import 'package:flutter/rendering.dart'; // 屏幕捕获并缩放为原始尺寸RGBA数据的函数 Future<Uint8List> captureScaledRgba(GlobalKey key) async { double dpr = ui.window.devicePixelRatio; final boundary = key.currentContext!.findRenderObject() as RenderRepaintBoundary; // 捕获高DPR图像保证质量 ui.Image highDprImage = boundary.toImageSync(pixelRatio: dpr); // 目标尺寸:Widget的原始逻辑尺寸 Size targetSize = boundary.size; int targetWidth = targetSize.width.toInt(); int targetHeight = targetSize.height.toInt(); // 创建录制器与画布,准备绘制缩放后的图像 final recorder = ui.PictureRecorder(); final canvas = Canvas( recorder, Rect.fromLTWH(0, 0, targetWidth.toDouble(), targetHeight.toDouble()), ); // 按比例缩放绘制高DPR图像,得到原始尺寸的图像 canvas.scale(1 / dpr); canvas.drawImage(highDprImage, Offset.zero, Paint()); // 生成缩放后的图像 ui.Image scaledImage = recorder.endRecording().toImageSync(targetWidth, targetHeight); // 提取原始RGBA格式的字节数据 final rawBytes = await scaledImage.toByteData(format: ui.ImageByteFormat.rawRgba); final uData = rawBytes!.buffer.asUint8List(); // 释放图像资源,录屏场景必须做,防止内存泄漏 highDprImage.dispose(); scaledImage.dispose(); return uData; }
关键说明
- 缩放逻辑:高DPR图像的像素数是原始逻辑尺寸×DPR,通过
canvas.scale(1/dpr)直接将图像缩放到原始尺寸,全程是底层图像绘制操作,性能远优于编码解码 - 资源释放:录屏时会频繁生成图像对象,必须调用
dispose()释放内存,否则会快速引发内存溢出 - 数据格式:最终输出的依然是原始RGBA字节流,完全符合你的性能与格式要求
内容的提问来源于stack exchange,提问作者jdevp2
相关产品推荐
相关产品推荐

