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

如何将签名PNG字节转换为Flutter SignatureController的Points?

将PNG签名图片还原为SignatureController的Points实现编辑功能

signature库本身没有提供直接从PNG图片还原SignaturePoint列表的API,我们需要通过图像像素分析来提取签名路径,具体实现步骤如下:

1. 添加图像处理依赖

在pubspec.yaml中添加image库,用于解析PNG字节并处理像素:

dependencies:
  signature: ^5.4.0 # 保持你当前使用的版本
  image: ^4.0.17 # 使用最新稳定版

2. 编写PNG转SignaturePoints的工具函数

通过解析PNG像素,提取签名颜色的坐标点,转换为SignaturePoint列表:

import 'package:image/image.dart' as img;
import 'package:signature/signature.dart';

Future<List<SignaturePoint>> pngToSignaturePoints(Uint8List pngBytes) async {
  // 解码PNG图片
  final decodedImage = img.decodePng(pngBytes);
  if (decodedImage == null) return [];

  final rawPoints = <SignaturePoint>[];
  // 遍历所有像素,提取白色签名点(假设签名为白色,背景为黑色)
  for (int y = 0; y < decodedImage.height; y++) {
    for (int x = 0; x < decodedImage.width; x++) {
      final pixel = decodedImage.getPixel(x, y);
      // 判断是否为白色像素(RGB值均为255)
      if (img.getRed(pixel) == 255 && img.getGreen(pixel) == 255 && img.getBlue(pixel) == 255) {
        rawPoints.add(SignaturePoint(
          Offset(x.toDouble(), y.toDouble()),
          pressure: 1.0, // 图片无法还原压力值,设为默认值
        ));
      }
    }
  }

  // 优化:去除连续重复的点,减少数据量
  final optimizedPoints = <SignaturePoint>[];
  Offset? lastOffset;
  for (final point in rawPoints) {
    if (lastOffset == null || point.offset != lastOffset) {
      optimizedPoints.add(point);
      lastOffset = point.offset;
    }
  }

  return optimizedPoints;
}

3. 实现点击图片编辑签名的逻辑

用GestureDetector包裹签名图片,点击时调用转换函数,将PNG字节转为SignaturePoint并更新控制器:

GestureDetector(
  onTap: () async {
    // 从存储的PNG字节转换为SignaturePoints
    final points = await pngToSignaturePoints(Uint8List.fromList(signature.pngBytes));
    // 更新签名控制器的points,签名板会自动刷新显示原有签名
    signatureController.points = points;
    // 这里可以跳转到签名编辑页面,或者直接显示签名板组件
    // 示例:Navigator.push(context, MaterialPageRoute(builder: (_) => SignatureEditPage(controller: signatureController)));
  },
  child: Image.memory(
    Uint8List.fromList(signature.pngBytes),
    width: MediaQuery.of(context).size.height * 0.1,
    fit: BoxFit.contain,
  ),
)

注意事项

  • 确保签名与背景颜色对比强烈,否则会提取错误的像素点;如果你的签名/背景颜色不同,需要修改像素判断逻辑。
  • 图片无法还原笔画的压力变化,因此生成的签名会使用固定的笔画宽度(取决于控制器的penStrokeWidth)。
  • 可以进一步优化像素遍历逻辑,比如只记录连续线段的起止点,减少points数量,提升签名板的渲染性能。

内容的提问来源于stack exchange,提问作者Michael

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.01 11:25:30