当前位置: 首页 > article >正文

Flutter Raw Image Provider

一般情况下,考虑网络传输效率,会采用算法来压缩这个数据,故而你会看到有各种各样的图像压缩算法和文件格式。

你可能会问什么情况下会有需要直接去加载一张图的原始rgba数据?

这里举个简单例子:分块加载图片。将图片解码后,分割成一个个矩形区域,每个矩形就有一个 raw rgba 数据,将其交给Image渲染,这样做可以降低一定的GPU 内存压力,减少出现GPU OOM 或黑屏的概率。

要支持 raw rgba ,其实很简单,在 dart:ui包下有个方法decodeImageFromPixels可以直接使用,前提是需要有原始的二进制数据、宽、高。

import ‘dart:ui’;

Future decodeRawRgba(ByteData bytes, int width, int height) {

final Completer completer = Completer();

decodeImageFromPixels(

bytes.buffer.asUint8List(),

width,

height,

PixelFormat.rgba8888,

completer.complete,

);

return completer.future;

}

有了这个 Image(dart:ui)对象就可以交给 RawImage Widget 来加载了。但RawImage太过于底层了,能不能只用 Image Widget呢?因为需要复用 LoadingBuilder这些逻辑。

当然可以。查看一下 Image Widget 的构造函数就知道,我们需要一个 ImageProvider,那么问题进一步简化到如何写一个ImageProvider 支持 raw rgba 数据。

实现一个 ImageProvider,我们需要实现 load这个关键方法。以MemoryImage为例:

class MemoryImage extends ImageProvider {

@override

ImageStreamCompleter load(MemoryImage key, DecoderCallback decode) {

return MultiFrameImageStreamCompleter(

codec: _loadAsync(key, decode),

scale: key.scale,

debugLabel: ‘MemoryImage(${describeIdentity(key.bytes)})’,

);

}

Future<ui.Codec> _loadAsync(MemoryImage key, DecoderCallback decode) {

return decode(bytes);

}

}

很显然,我们需要想一个方法构造出raw rgba 数据的 Codec

其实秘密就在 decodeImageFromPixels这个方法实现里:

void decodeImageFromPixels(

Uint8List pixels,

int width,

int height,

PixelFormat format,

ImageDecoderCallback callback, {

int? rowBytes,

int? targetWidth,

int? targetHeight,

bool allowUpscaling = true,

}) {

if (targetWidth != null) {

assert(allowUpscaling || targetWidth <= width);

}

if (targetHeight != null) {

assert(allowUpscaling || targetHeight <= height);

}

ImmutableBuffer.fromUint8List(pixels)

.then((ImmutableBuffer buffer) {

final ImageDescriptor descriptor = ImageDescriptor.raw(

buffer,

width: width,

height: height,

rowBytes: rowBytes,

pixelFormat: format,

);

if (!allowUpscaling) {

if (targetWidth != null && targetWidth! > descriptor.width) {

targetWidth = descriptor.width;

}

if (targetHeight != null && targetHeight! > descriptor.height) {

targetHeight = descriptor.height;

}

}

descriptor

.instantiateCodec(

targetWidth: targetWidth,

targetHeight: targetHeight,

)

.then((Codec codec) => codec.getNextFrame())

.then((FrameInfo frameInfo) => callback(frameInfo.image));

});

}

先从数据构造出ImageDescriptor,再把descriptor.instantiateCodec()这一步抽出来就可以获取 raw rgba 数据的 Codec,进而实现一个自己的RawImageProvider了。

如:


http://www.kler.cn/a/530240.html

相关文章:

  • 小程序的协同工作与发布
  • 使用LLaMA-Factory对AI进行认知的微调
  • 本地部署DeepSeek
  • 程序诗篇里的灵动笔触:指针绘就数据的梦幻蓝图<2>
  • 【AI绘画】MidJourney关键词{Prompt}全面整理
  • Windows系统本地部署deepseek 更改目录
  • Python 中 `finally` 的执行时机与 `return` 的微妙关系
  • SD存储卡功能特性解析
  • 【C++语言】卡码网语言基础课系列----11. 句子缩写
  • DeepSeek让英伟达狂跌三年?
  • openEuler系统磁盘管理方法
  • Ubuntu 下 nginx-1.24.0 源码分析 - ngx_strerror_init()函数
  • OpenAI发布o3-mini:免费推理模型,DeepSeek引发的反思
  • MySQL 基础学习(4):条件查询(WHERE)更新操作(UPDATE)删除操作(DELETE)分页查询(LIMIT)
  • 算法随笔_36: 复写零
  • 面向初学者的卷积神经网络_卷积神经网络好学吗
  • C++泛型编程指南03-CTAD
  • shell编程(1)——shell介绍
  • Hive分区和分桶
  • unity中的动画混合树
  • Games104——网络游戏的进阶架构
  • 分享10个实用的Python工具的源码,支持定制
  • Java项目: 基于SpringBoot+mybatis+maven+mysql实现的图书管理系统(含源码+数据库+答辩PPT+毕业论文)
  • Python爬虫从入门到精通(三)简单爬虫的实现_爬虫tl
  • 问deepseek,如何看待ai降低学习成本而导致软件开发岗位需求降低,和工资下降。 软件从业人员何去何从?
  • 陆游的《诗人苦学说》:从藻绘到“功夫在诗外”(中英双语)mastery lies beyond poetry