Flutter 像素编辑器#04 | 导入导出图像

devtools/2024/12/22 18:07:28/

theme: cyanosis

1. 本文目的

本系列,将通过 Flutter 实现一个全平台的像素编辑器应用。源码见开源项目 【pix_editor】。在前三篇中,我们已经完成了一个简易的图像编辑器,并且简单引入了图层的概念,支持切换图层显示不同的像素画面。

  • 《Flutter 像素编辑器#01 | 像素网格》
  • 《Flutter 像素编辑器#02 | 配置编辑》
  • 《Flutter 像素编辑器#03 | 像素图层》

本文的目标两个:

[1]. 支持导入一张图像,将其像素化地展示在界面中:

01.gif

[2]. 像素点可编辑,编辑完成后,可以将图片进行导出到对应文件夹:

02.gif

image.png


2. 图像的导入

图像本质上是由一个个像素点构成的二维空间点阵。在像素编辑器中,每个单元格记录着一份像素信息,我们需要根据网格行列数,对图像的像素信息进行采样。行列数会直接决定当前区域中像素信息相对于原图像的的完整程度。比如下面分别是 16*1632*3264*64 的网格采样同一图像的呈现效果:

| 16*16 | 32*32 | 64*64 | | --- | --- |--- | | image.png | image.png |image.png

当前需求的关键点在于:如何获取原图像的所有像素点信息,然后根据像素点映射生成 PixCell 列表数据进行呈现。此时需要依赖 image类库。 现在在业务逻辑对象 PixPaintLogic 中增加一个 setImage 方法,传入用户选择的文件路径,使用 img.decodeImage 方法解码图片生成 img.Image 对象:

```dart ---->[lib/bloc/pixpaintlogic.dart]---- import 'package:image/image.dart' as img;

void setImage(String filePath) async { File file = File(filePath); img.Image? pixImage = img.decodeImage(await file.readAsBytes()); if(pixImage==null){ return; } setPixByImage(pixImage); } ```

setPixByImage 方法中处理核心逻辑:遍历网格的行列数,从 image 中采样对应的像素值。其中 rate 标识格点像素相较于真实像素的坐标缩放比例,也就是像素采样的间隔。将非透明色的像素点,加入到 PixCell 列表中:

```dart void setPixByImage(img.Image image) { List cells = []; int minSize = min(image.width, image.height); int minCount = min(row, column); int count = minSize.clamp(0, minCount); double rate = minSize / count;

for (int x = 0; x < count; x++) { for (int y = 0; y < count; y++) { var pixel = image.getPixel((y * rate).toInt(), (x * rate).toInt()); var color = Color.fromARGB( pixel.a.toInt(), pixel.r.toInt(), pixel.g.toInt(), pixel.b.toInt()); if (color != Colors.transparent) { cells.add(PixCell(color: color, position: (y, x))); } } } setPixCells(cells); } ```

最后通过 setPixCells 方法,将生成的 PixCell 列表加入到状态数据中,并发送更新通知,让画板进行变化:

dart void setPixCells(List<PixCell> cells) { pixCells.clear(); pixCells.addAll(cells); notifyListeners(); activePixLayer.update(); }


3. 图像的导出

本来是想通过 Canvas 进行绘制导出图片的,但是效果并不理想,因为 Flutter 的 1px 问题,并不适合绘制细小的像素。 image类库 中提供了像素级的操作,直接生成 png 图像:

image.png

如下所示,先创建一个 pixLayer 网格宽高的 img.Image 图像,通过数为 4 个,默认是 3 没有透明度。然后遍历 pixLayer#pixCells 为生成的 image 对象设置像素信息。最后只需要 img.encodePng(image) 即可进行编码得到字节列表数据:

```dart PixPaintLogic paintLogic = PixPaintScope.read(context); PixLayer pixLayer = paintLogic.activePixLayer;

final image = img.Image( width: pixLayer.row, height: pixLayer.column, numChannels: 4, );

for (PixCell pix in pixLayer.pixCells) { Color color = pix.color; image.setPixelRgba( pix.position.$1, pix.position.$2, color.red, color.green, color.blue, color.alpha, ); }

final Uint8List byteData = img.encodePng(image); ```


有了字节列表数据之后,通过 FilePicker.platform.saveFile 选择保存文件,然后写入文件即可:

dart String? result = await FilePicker.platform.saveFile(type: FileType.image); if (result != null) { File file = File(result); await file.writeAsBytes(byteData); }


到这里,导入导出图像的功能就基本完成了,这样像素编辑的基本功能就能运转了,但目前只支持正方形的图片,后续会继续优化,支持矩形的网格。可以多多关注 【pix_editor】 的发展。


http://www.ppmy.cn/devtools/46332.html

相关文章

Qt-qrencode生成二维码

Qt-qrencode开发-生成二维码&#x1f4c0; 文章目录 Qt-qrencode开发-生成二维码&#x1f4c0;[toc]1、概述&#x1f4f8;2、实现效果&#x1f4bd;3、编译qrencode&#x1f50d;4、在QT中引入编译为静态库的QRencode5、在Qt中直接使用QRencode源码6、在Qt中使用QRencode生成二…

OceanBase v4.2 特性解析:新增三种临时表功能,更多的Oracle语句兼容

特性说明 在Oracle模式下&#xff0c;OceanBase临时表已经实现了基本的create、select、insert、delete、update等功能。为了满足更多客户的需求&#xff0c;OceanBase正在扩展临时表的功能&#xff0c;例如支持merge into和insert all操作。merge into允许用户将源表中的数据…

无线网络SCI期刊,中科院4区,录用难度不大,出版稳定

一、期刊名称 Wireless Networks 二、期刊简介概况 期刊类型&#xff1a;SCI 学科领域&#xff1a;计算机科学 影响因子&#xff1a;3.0 中科院分区&#xff1a;4区 三、期刊征稿范围 无线通信革命正在给数据网络、电信带来根本性的变化&#xff0c;并使集成网络成为现实…

关于找暑期实习后的一些反思

日期 2024年6月3日 写在前面&#xff1a;距离研究生毕业还有9个月&#xff0c;前端时间一直在不停地投简历&#xff0c;不停地刷笔试题&#xff0c;不停地被拒绝&#xff0c;今天悬着的心终于死透了&#xff0c;心情还是比较糟糕的&#xff0c;可能唯一的安慰就是一篇小论文终于…

教育小程序的性能优化:从前端到后端的综合提升策略

随着教育小程序的普及&#xff0c;其性能直接影响用户体验和教学效果。本文将从前端到后端&#xff0c;详细探讨教育小程序的性能优化策略&#xff0c;帮助开发者打造高效、流畅的教育应用。 一、前端性能优化策略 代码优化 减少HTTP请求&#xff1a;合并CSS、JavaScript文件…

驱动开发学习之新旧字符设备接口,自动创建设备的点灯

1.前言 本章将介绍新旧字符设备接口,以及自动创建设备节点的点灯实验。 2.实验原理介绍 2.1.寄存器知识 学习过单片机的兄弟都知道&#xff0c;点灯有以下步骤&#xff1a; &#xff08;1&#xff09;开启相应的GPIO时钟 &#xff08;2&#xff09;如果需要配置复用&…

【Qt秘籍】[002]-开始你的Qt之旅-下载

一、Qt的开发工具有哪些&#xff1f; Qt的开发工具概述Qt支持多种开发工具&#xff0c;其中最常见的开发工具是 1.QtCreator 【易上手/有少量bug/适合新手】 2.VisualStudio 【功能强大/易出错/需要更多额外配置】 3.Eclipse 【清朝老兵IDE/不建议使用】 【注意&#xff1…

每日一题——Java编程练习题

题目&#xff1a; 给你一个整数 x 。如果 x 是一个回文整数&#xff0c;打印 true &#xff0c;否则&#xff0c;返回 false 。 解释&#xff1a;回文数是指正序&#xff08;从左向右&#xff09;和倒序&#xff08;从右向左&#xff09;读都是一样的整数。 例如&#xff0c…