Flutter图片编码插件jpeg_encode的使用

发布于 1周前 作者 ionicwang 来自 Flutter

Flutter图片编码插件jpeg_encode的使用

简介

在Flutter中,dart:ui引擎(Skia)仅支持PNG和原始RGBA格式,而不支持JPEG。根据源代码注释,Skia团队并不打算添加更多格式,这些功能应由外部包来实现。jpeg_encode插件就是一个专门用于将图像转换为JPEG格式的最小化编码器。它不提供额外的功能,只专注于创建最简单的JPEG文件。虽然不一定是最优或最压缩的JPEG文件,但其效果仍然相当不错。

该插件是基于Jon Olick的现有实现的Dart版本移植而来。

使用方法

1. 将图像转换为JPEG格式

假设你已经有一个dart:uiImage对象,可能是从某个来源获取的:

import "dart:ui" as ui;
import 'package:jpeg_encode/jpeg_encode.dart'; // 导入jpeg_encode包
import 'dart:typed_data';
import 'dart:io';

// 假设你有一个Uint8List类型的字节数据
Uint8List bytes;

// 创建一个图像解码器并获取图像帧
final codec = await ui.instantiateImageCodec(bytes);
final frame = await codec.getNextFrame();
final image = frame.image;

接下来,你可以将这个Image对象转换为JPEG格式。quality参数的取值范围是0到100,表示压缩质量,数值越大,图像质量越高,文件大小也越大:

// 将图像转换为原始RGBA格式的字节数据
final data = await image.toByteData(format: ui.ImageByteFormat.rawRgba);

// 使用JpegEncoder进行压缩,生成JPEG格式的字节数据
final jpg = JpegEncoder().compress(
  data!.buffer.asUint8List(), // 图像的原始RGBA字节数据
  image.width,                // 图像宽度
  image.height,               // 图像高度
  90                          // 压缩质量 (0-100)
);
2. 保存JPEG文件

在Flutter中保存文件非常简单,可以直接使用File类将字节数据写入文件系统:

// 同步保存
File(path).writeAsBytesSync(jpg);

// 或者异步保存
await File(path).writeAsBytes(jpg);

完整示例Demo

以下是一个完整的示例,展示了如何从网络加载图像、将其转换为JPEG格式并保存到本地文件系统中:

import 'dart:io';
import 'dart:typed_data';
import 'dart:ui' as ui;
import 'package:flutter/material.dart';
import 'package:jpeg_encode/jpeg_encode.dart';
import 'package:image_picker/image_picker.dart'; // 用于选择本地图片
import 'package:path_provider/path_provider.dart'; // 用于获取应用目录

void main() {
  runApp(MyApp());
}

class MyApp extends StatelessWidget {
  [@override](/user/override)
  Widget build(BuildContext context) {
    return MaterialApp(
      home: Scaffold(
        appBar: AppBar(title: Text('JPEG Encoder Demo')),
        body: Center(
          child: ElevatedButton(
            onPressed: _convertAndSaveImage,
            child: Text('选择图片并转换为JPEG'),
          ),
        ),
      ),
    );
  }

  Future<void> _convertAndSaveImage() async {
    // 使用image_picker选择一张图片
    final picker = ImagePicker();
    final pickedFile = await picker.pickImage(source: ImageSource.gallery);

    if (pickedFile == null) return;

    // 读取图片的字节数据
    final bytes = await File(pickedFile.path).readAsBytes();

    // 创建图像解码器并获取图像帧
    final codec = await ui.instantiateImageCodec(bytes);
    final frame = await codec.getNextFrame();
    final image = frame.image;

    // 将图像转换为原始RGBA格式的字节数据
    final data = await image.toByteData(format: ui.ImageByteFormat.rawRgba);

    // 使用JpegEncoder进行压缩,生成JPEG格式的字节数据
    final jpg = JpegEncoder().compress(
      data!.buffer.asUint8List(),
      image.width,
      image.height,
      90, // 压缩质量 (0-100)
    );

    // 获取应用的临时目录
    final directory = await getTemporaryDirectory();
    final path = '${directory.path}/output.jpg';

    // 保存JPEG文件
    await File(path).writeAsBytes(jpg);

    // 提示用户保存成功
    ScaffoldMessenger.of(context).showSnackBar(
      SnackBar(content: Text('图片已成功保存到 $path')),
    );
  }
}

更多关于Flutter图片编码插件jpeg_encode的使用的实战系列教程也可以访问 https://www.itying.com/category-92-b0.html

1 回复

更多关于Flutter图片编码插件jpeg_encode的使用的实战系列教程也可以访问 https://www.itying.com/category-92-b0.html


当然,以下是如何在Flutter项目中使用jpeg_encode插件对图片进行JPEG编码的示例代码。

首先,确保你已经在pubspec.yaml文件中添加了jpeg_encode依赖项:

dependencies:
  flutter:
    sdk: flutter
  jpeg_encode: ^0.1.0  # 请检查最新版本号

然后,运行flutter pub get来安装依赖项。

接下来是一个完整的示例,展示如何使用jpeg_encode插件将Uint8List格式的图片数据编码为JPEG格式的字节数组:

import 'package:flutter/material.dart';
import 'package:jpeg_encode/jpeg_encode.dart';
import 'dart:typed_data';
import 'dart:ui' as ui;

void main() {
  runApp(MyApp());
}

class MyApp extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      home: Scaffold(
        appBar: AppBar(
          title: Text('JPEG Encode Example'),
        ),
        body: Center(
          child: JPEGEncodeExample(),
        ),
      ),
    );
  }
}

class JPEGEncodeExample extends StatefulWidget {
  @override
  _JPEGEncodeExampleState createState() => _JPEGEncodeExampleState();
}

class _JPEGEncodeExampleState extends State<JPEGEncodeExample> {
  Uint8List? jpegBytes;

  @override
  Widget build(BuildContext context) {
    return Column(
      mainAxisAlignment: MainAxisAlignment.center,
      children: [
        if (jpegBytes != null)
          Image.memory(jpegBytes!),
        ElevatedButton(
          onPressed: () async {
            // 生成一个示例图片(红色方块)
            final PictureRecorder recorder = PictureRecorder();
            final Canvas canvas = Canvas(recorder);
            final Paint paint = Paint()..color = Colors.red;
            final Rect rect = Rect.fromLTWH(0, 0, 256, 256);
            canvas.drawRect(rect, paint);
            final Picture picture = recorder.endRecording();

            // 将Picture转换为Image
            final Image image = await picture.toImage(256, 256);

            // 将Image转换为字节数据(RGBA格式)
            final ByteData? byteData = await image.toByteData(format: ui.ImageByteFormat.rawRgba, quality: 100);
            if (byteData == null) {
              return;
            }

            // 获取RGBA格式的Uint8List
            final Uint8List rgbaBytes = byteData.buffer.asUint8List();

            // 使用jpeg_encode插件进行JPEG编码
            jpegBytes = encodeJpg(rgbaBytes, 256, 256, quality: 90);

            // 更新UI
            setState(() {});
          },
          child: Text('Encode Image to JPEG'),
        ),
      ],
    );
  }
}

代码说明:

  1. 依赖项:在pubspec.yaml文件中添加了jpeg_encode依赖项。

  2. 生成示例图片

    • 使用PictureRecorderCanvas生成一个红色方块的图片。
    • 使用picture.toImagePicture转换为Image
  3. 将Image转换为字节数据

    • 使用image.toByteDataImage转换为RGBA格式的字节数据(Uint8List)。
  4. JPEG编码

    • 使用jpeg_encode插件的encodeJpg函数将RGBA格式的字节数据编码为JPEG格式的字节数组。
  5. 显示JPEG图片

    • 使用Image.memory将编码后的JPEG字节数组显示为图片。

这个示例展示了如何使用jpeg_encode插件对图片进行JPEG编码,并将结果显示在Flutter应用中。注意,encodeJpg函数中的quality参数用于控制JPEG图片的质量(0-100)。

回到顶部