Brandon Pillay
Brandon Pillay

Reputation: 1166

How to print to a thermal printer from Canvas to image?

I'm using the blue_thermal_printer with Flutter Android to try and create an image from a Canvas recording but the image prints as a solid block instead of an image:

enter image description here

This class is responsible for creating the bytedata of the image:

import 'dart:typed_data';
import 'dart:ui' as ui;

import 'package:flutter/material.dart';

class LabelPainter {
  Future<ByteData> getImageByteData() async {
    int _width = 60;
    int _height = 60;
    ui.PictureRecorder recorder = new ui.PictureRecorder();

    Paint _paint = Paint()
      ..style = PaintingStyle.stroke
      ..strokeWidth = 4.0;

    Canvas c = new Canvas(recorder);
    c.drawRRect(RRect.fromLTRBAndCorners(20, 30, 40, 50), _paint);
    _paint.color = Colors.red;
    c.drawRect(Rect.fromLTWH(10, 10, 10, 10), _paint);
    _paint.color = Colors.blue;
    c.drawRect(
        Rect.fromCenter(center: Offset(50, 50), height: 50, width: 50), _paint);
    _paint.color = Colors.black;
    c.drawRect(
        Rect.fromPoints(
            Offset(0, 0), Offset(_width.toDouble(), _height.toDouble())),
        _paint);
    // c.drawPaint(Paint()); // etc
    ui.Picture p = recorder.endRecording();
    ui.Image _uiImg = await p.toImage(
        _width, _height); //.toByteData(format: ImageByteFormat.png);

    ByteData _byteData =
        await _uiImg.toByteData(format: ui.ImageByteFormat.png);
    return _byteData;
  }
}

This is part of the status widget that gets the ByteData then saves the image to the file directory:

class _PrinterState extends State<Printer> {
    String pathImage;
  LabelPainter _labelPainter = new LabelPainter();
  @override
  void initState() {
    super.initState();
    initSavetoPath();
  }

  initSavetoPath() async {
    //read and write
    //image max 300px X 300px
    final filename = 'yourlogo.png';
    // var bytes = await rootBundle.load("images/logo.png");
    ByteData bytes = await _labelPainter.getImageByteData();
    String dir = (await getApplicationDocumentsDirectory()).path;
    writeToFile(bytes, '$dir/$filename');
    setState(() {
      pathImage = '$dir/$filename';
    });
  }

  @override
  Widget build(BuildContext context) {
    return Container();
  }

  //write to app path
  Future<void> writeToFile(ByteData data, String path) {
    final buffer = data.buffer;
    return new File(path).writeAsBytes(
        buffer.asUint8List(data.offsetInBytes, data.lengthInBytes));
  }
}

This is the method I call when I want to print the image:

  void _tesPrint() async {
    //SIZE
    // 0- normal size text
    // 1- only bold text
    // 2- bold with medium text
    // 3- bold with large text
    //ALIGN
    // 0- ESC_ALIGN_LEFT
    // 1- ESC_ALIGN_CENTER
    // 2- ESC_ALIGN_RIGHT
    bluetooth.isConnected.then((isConnected) async {
      if (isConnected) {;
        // bluetooth.printImageBytes(await _labelPainter.getImageBytesUint());
        bluetooth.printImage(pathImage);
        // bluetooth.printNewLine();
        // bluetooth.printCustom("Terimakasih", 2, 1);
        // bluetooth.printNewLine();
        // bluetooth.printQRcode("Insert Your Own Text to Generate", 50, 50, 0);
        // bluetooth.paperCut();
      }
    });

Upvotes: 2

Views: 1891

Answers (1)

Renato Aguiar
Renato Aguiar

Reputation: 91

I already had this problem.

Only difference is that i generate image from widget, like a screenshoot.

So the same problem occours to share and print, the image is totally black.

The solution was to provide a white background and then, the problem was solved. The image content can be visualized.

Upvotes: 1

Related Questions