Flutter Web端img.Image编辑后转Uint8List显示问题求助
Flutter Web端image库编辑后转Uint8List显示方案
核心出错原因:
- 上传得到的原始字节是标准图片格式(PNG/JPG)的压缩数据,必须先解码为
img.Image像素对象才能做滤镜、绘制等编辑操作 - 编辑完成后的
img.Image是内存中存储的原始像素矩阵,必须重新编码为标准图片格式的字节流,才能被Image.memory组件识别加载。
修改后的可运行代码
只需要调整getImageWeb方法的逻辑即可,完整代码如下:
import 'dart:typed_data'; import 'package:flutter/foundation.dart'; import 'package:flutter/material.dart'; import 'package:image/image.dart' as img; import 'package:image_picker/image_picker.dart'; import 'package:image_picker_web/image_picker_web.dart'; void main() { runApp(const MyApp()); } class MyApp extends StatelessWidget { const MyApp({Key? key}) : super(key: key); @override Widget build(BuildContext context) { return MaterialApp( title: 'Test', theme: ThemeData( primarySwatch: Colors.blue, ), home: const MyHomePage(title: 'Draw Picture Homepage'), ); } } class MyHomePage extends StatefulWidget { const MyHomePage({Key? key, required this.title}) : super(key: key); final String title; @override State<MyHomePage> createState() => _MyHomePageState(); } class _MyHomePageState extends State<MyHomePage> { late Uint8List pickedImage; bool imageAvailable = false; @override void initState() { super.initState(); } getImageWeb() async { final fromPicker = await ImagePickerWeb.getImageAsBytes(); if (fromPicker == null) return; // 1. 解码原始图片字节为img.Image可操作对象 img.Image? originalImg = img.decodeImage(fromPicker); if (originalImg == null) return; // 2. 执行图片编辑操作,以下为示例效果 // 转为灰度图 img.Image editedImg = img.grayscale(originalImg); // 绘制红色直线 img.drawLine(editedImg, 0, 0, 320, 240, img.getColor(255, 0, 0), thickness: 3); // 绘制文字 img.drawString(editedImg, img.arial_24, 10, 10, 'Edited on Flutter Web'); // 高斯模糊效果 // img.gaussianBlur(editedImg, 10); // 3. 将编辑后的img.Image重新编码为PNG格式的Uint8List Uint8List editedBytes = Uint8List.fromList(img.encodePng(editedImg)); setState(() { pickedImage = editedBytes; imageAvailable = true; }); } @override Widget build(BuildContext context) { return Scaffold( appBar: AppBar( title: Text(widget.title), ), body: Center( child: Column( mainAxisAlignment: MainAxisAlignment.center, children: [ ElevatedButton( onPressed: () => getImageWeb(), child: const Text('Select Image'), ), Container( width: 300, padding: const EdgeInsets.only(top: 20), child: imageAvailable ? Image.memory(pickedImage) : const SizedBox(height: 10), ), const Text('Test'), ], ), ), ); } }
注意事项
- 如果需要更小的输出体积,可以把编码方法替换为
img.encodeJpg(editedImg, quality: 85),注意JPG格式不支持透明通道 - 分辨率超过2000*2000的大图做编辑、编码操作时,建议放到独立isolate中执行,避免阻塞UI导致页面卡顿
- 所有
image库的绘制、滤镜操作都必须传入解码后的img.Image对象,直接对原始压缩字节操作无效。
内容的提问来源于stack exchange,提问作者romu2000
相关产品推荐
相关产品推荐

