Flutter画布绘图后保存图片如何避免画质下降?
画质下降的核心原因
你当前的代码画质下降主要来自两个问题:
RenderRepaintBoundary的toImage()方法默认使用pixelRatio = 1.0生成图片,远低于绝大多数移动设备的实际屏幕像素密度,导出的图片相当于把屏幕显示的内容拉伸放大,自然会模糊。- 如果你是在原始高清图片上叠加绘制内容,直接截取屏幕上的控件渲染结果,导出的分辨率最高只能达到控件在屏幕上的渲染尺寸,远低于原始图片的固有分辨率。
调整方案
方案1:快速修复(适配屏幕分辨率导出)
给toImage方法传入当前设备的像素密度参数即可大幅提升导出画质,修改后代码如下:
Future<void> _save() async { RenderRepaintBoundary boundary = globalKey.currentContext.findRenderObject(); // 传入设备像素比,导出和屏幕显示清晰度一致的图片 double pixelRatio = MediaQuery.of(context).devicePixelRatio; ui.Image image = await boundary.toImage(pixelRatio: pixelRatio); ByteData byteData = await image.toByteData(format: ui.ImageByteFormat.png); Uint8List pngBytes = byteData.buffer.asUint8List(); Navigator.pop(context, pngBytes); }
方案2:无损导出(适配原始图片分辨率,适合在原图上绘图的场景)
如果需要保留原始图片的高清分辨率,不要依赖控件截图,改用离屏画布直接渲染:
- 先拿到原始图片的宽高尺寸
- 创建对应尺寸的
ui.PictureRecorder和画布 - 先把原始高清图绘制到画布上,再把所有用户绘制的路径、图形按比例绘制到画布上
- 直接从画布生成对应分辨率的图片导出,完全不会损失画质
额外注意事项
PNG格式本身是无损压缩,ui.ImageByteFormat.png导出不会额外损失画质,不要在导出后额外做质量压缩操作即可。
内容的提问来源于stack exchange,提问作者Hoo
相关产品推荐
相关产品推荐

