Flutter工具类插件esc_utils的使用

Flutter工具类插件esc_utils的使用

esc_utils 是一个用于将图像数据转换为小票打印机可识别的字节数组的工具。该工具使用 image: ^3.0.2 库进行图像处理。

使用示例

1. 获取图片数据转 Uint8List
// 通过文件路径获取图片
static Future<Uint8List> getImage(String imgPath) async {
  final imgFile = File(imgPath);
  final exist = await imgFile.exists();
  if(exist) {
    return imgFile.readAsBytes();
  } else {
    throw Exception('print imgFile is not exist');
  }
}
2. Uint8ListESC 字节数组
import 'package:image/image.dart' as img;

// Uint8List 转 ESC 字节数组
static Future<List<int>> decodeBytes(Uint8List imgData) async {
  final img.Image image = await cropImage(imgData); // 假设 cropImage 是一个已定义的方法
  Generator generator = Generator();
  List<int> bytes = [];
  
  // 打印机状态重置
  bytes += generator.reset();
  
  // 打印光栅位图
  bytes += generator.imageRaster(image);
  
  // 走纸 2mm
  bytes += generator.feed(2);
  
  // 切刀
  bytes += generator.cut();
  
  return bytes;
}

注意事项

  1. 分块发送:通常不会把一整张图片直接发给打印机,那样太大。都会分割成小图片逐个发送。比如数据太大导致打印机内存溢出输出乱码。
  2. 图片尺寸:小票机,目前常用尺寸为 80mm、58mm。通常 1mm 等于 8个像素,因此,适合小票打印机打印的图片像素尺寸应为:558px、372px。(因为宽度适配在实际打印中有偏差,不宜设置为完全吻合)
  3. 图片宽度:打印的图片宽度像素太大会造成打印无反应。

长图切割为多张小图示例

static Future<List<img.Image>> decodeImage(
    Uint8List imgData, {
    int imgSizeLimit = 550 * 1000,
  }) async {
  final img.Image crop = await cropImage(imgData); // 假设 cropImage 是一个已定义的方法
  final cropWidth = crop.width;
  img.Image targetImg = crop;
  
  // 缩放处理,保持图片宽度能被8整除
  if (cropWidth % 8 != 0) {
    targetImg = await resizeImage(
      crop,
      targetWidth: cropWidth ~/ 8 * 8,
      targetHeight: crop.height,
    );
  }
  
  final targetWidth = targetImg.width;
  final targetHeight = targetImg.height;
  final result = <img.Image>[];
  
  if (targetWidth * targetHeight > imgSizeLimit) {
    LogTool.log('esc 长图开启切割');
    int splitItemHeight = imgSizeLimit ~/ targetWidth;

    int splitCount = targetHeight ~/ splitItemHeight;

    int lastItemHeight = targetHeight % splitItemHeight;

    for (int index = 0; index < splitCount; index++) {
      final splitItem = img.copyCrop(
        targetImg,
        0,
        splitItemHeight * index,
        targetWidth,
        splitItemHeight,
      );
      result.add(splitItem);
    }
    
    LogTool.log(
        '切图 * $splitCount 份 width($targetWidth) height($splitItemHeight)');

    if (lastItemHeight > 0) {
      final lastItem = img.copyCrop(
        crop,
        0,
        splitItemHeight * splitCount,
        targetWidth,
        lastItemHeight,
      );
      result.add(lastItem);
      LogTool.log('切图 * 1 份 width($targetWidth) height($lastItemHeight)');
    }
  } else {
    result.add(crop);
    LogTool.log('esc 无需切割 width($targetWidth) height($targetHeight)');
  }
  return result;
}

更多关于Flutter工具类插件esc_utils的使用的实战教程也可以访问 https://www.itying.com/category-92-b0.html

1 回复

更多关于Flutter工具类插件esc_utils的使用的实战系列教程也可以访问 https://www.itying.com/category-92-b0.html


esc_utils 是一个用于 Flutter 的插件,专门用于与 ESC/POS 打印机进行通信和打印。ESC/POS 是一种常见的打印机命令语言,广泛用于热敏打印机和点阵打印机。esc_utils 插件提供了与这些打印机进行通信的功能,并支持生成 ESC/POS 命令。

安装 esc_utils 插件

首先,你需要在 pubspec.yaml 文件中添加 esc_utils 插件的依赖:

dependencies:
  esc_utils: ^1.0.0  # 请根据最新版本号进行更新

然后运行 flutter pub get 来获取依赖。

使用 esc_utils

1. 导入插件

import 'package:esc_utils/esc_utils.dart';

2. 创建 ESC/POS 命令

esc_utils 提供了一个 EscPos 类,用于生成 ESC/POS 命令。你可以使用它来创建各种打印命令,例如文本、图像、条形码等。

final escPos = EscPos();

// 添加文本
escPos.text('Hello, World!');

// 设置文本样式
escPos.text('Bold Text', styles: PosStyles(bold: true));
escPos.text('Large Text', styles: PosStyles(width: PosTextSize.size2, height: PosTextSize.size2));

// 添加换行
escPos.feed(2);

// 添加条形码
escPos.barcode(Barcode.upcA('123456789012'));

// 添加二维码
escPos.qrcode('https://example.com');

// 添加图像
final ByteData data = await rootBundle.load('assets/logo.png');
final Uint8List bytes = data.buffer.asUint8List();
escPos.image(bytes);

// 切纸
escPos.cut();

3. 发送命令到打印机

生成的 ESC/POS 命令可以通过蓝牙、USB 或网络发送到打印机。具体的通信方式取决于你的打印机和平台。

例如,使用蓝牙发送命令:

import 'package:flutter_blue/flutter_blue.dart';

void sendToPrinter(List<int> commands) async {
  FlutterBlue flutterBlue = FlutterBlue.instance;

  // 发现设备
  flutterBlue.startScan(timeout: Duration(seconds: 4));
  flutterBlue.scanResults.listen((results) {
    for (ScanResult result in results) {
      if (result.device.name == 'Your Printer Name') {
        // 连接设备
        await result.device.connect();

        // 找到打印服务
        List<BluetoothService> services = await result.device.discoverServices();
        for (BluetoothService service in services) {
          if (service.uuid.toString() == 'Your Service UUID') {
            // 找到打印特征
            for (BluetoothCharacteristic characteristic in service.characteristics) {
              if (characteristic.uuid.toString() == 'Your Characteristic UUID') {
                // 发送命令
                await characteristic.write(commands);
              }
            }
          }
        }
      }
    }
  });
}

// 使用
sendToPrinter(escPos.bytes);

4. 处理打印机响应

你可以监听打印机的响应,以便处理错误或确认打印任务是否成功完成。

characteristic.value.listen((value) {
  print('Printer response: $value');
});
回到顶部