You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.09.02 23:09:31