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

Dart加载Ui.Image时实现水平翻转 避免Canvas操作性能损耗

预加载阶段实现图片水平翻转方案

完全可以在图片加载阶段一次性完成水平翻转,后续Canvas绘制无需任何额外操作,重绘效率和普通未处理图片完全一致。注意不要直接反转压缩格式(PNG/JPG)的原始二进制字节,该操作会导致图片解码失败,必须等图片解码为原始RGBA像素数组后再做翻转处理。

修改后完整代码

import 'dart:ui' as ui;
import 'package:flutter/services.dart';

static Future<ui.Image> loadFlippedImage(String imagePath) async {
  ByteData bd = await rootBundle.load(imagePath);
  final Uint8List compressedBytes = Uint8List.view(bd.buffer);
  final ui.Codec codec = await ui.instantiateImageCodec(compressedBytes);
  final ui.Image originalImage = (await codec.getNextFrame()).image;

  // 读取原始图片RGBA像素数据
  final ByteData? originalByteData = await originalImage.toByteData(
    format: ui.ImageByteFormat.rawRgba
  );
  if (originalByteData == null) {
    originalImage.dispose();
    throw Exception('图片像素读取失败');
  }
  final Uint8List originalPixels = originalByteData.buffer.asUint8List();
  final int width = originalImage.width;
  final int height = originalImage.height;
  final int bytesPerRow = width * 4; // 每个像素占4字节(RGBA各1字节)
  final Uint8List flippedPixels = Uint8List(originalPixels.length);

  // 逐行翻转像素
  for (int y = 0; y < height; y++) {
    final int rowStartOffset = y * bytesPerRow;
    for (int x = 0; x < width; x++) {
      // 计算原始像素和翻转后像素的对应位置
      final int originalOffset = rowStartOffset + x * 4;
      final int flippedOffset = rowStartOffset + (width - 1 - x) * 4;
      // 完整复制RGBA四个通道的值
      flippedPixels[flippedOffset] = originalPixels[originalOffset];
      flippedPixels[flippedOffset + 1] = originalPixels[originalOffset + 1];
      flippedPixels[flippedOffset + 2] = originalPixels[originalOffset + 2];
      flippedPixels[flippedOffset + 3] = originalPixels[originalOffset + 3];
    }
  }

  // 生成翻转后的新Image对象
  final ui.Image flippedImage = await ui.Image.fromBytes(
    width: width,
    height: height,
    bytes: flippedPixels.buffer.asByteData(),
    format: ui.ImageByteFormat.rawRgba,
  );

  // 释放原始未翻转图片的内存,避免冗余占用
  originalImage.dispose();
  return flippedImage;
}

关键说明

  • 整个翻转逻辑仅在图片加载阶段执行一次,后续Canvas绘制直接使用返回的flippedImage即可,不需要做任何矩阵变换或翻转操作,重绘效率完全满足高性能场景要求
  • 该方案兼容带透明通道的图片,会完整保留Alpha通道信息
  • 如果需要处理多帧动图,只需循环读取codec的所有帧,对每一帧都执行上述翻转逻辑即可

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.09.27 05:45:00