Barcode problem

Hello everyone,
I’m close to finishing my app, but I’ve hit a roadblock that I’ve been stuck on for days. Here’s the basic logic I want to implement:

On the “Print Barcode” page, I generate a barcode with a random, unassigned number and print it using a thermal printer (a visual barcode).
Later, when I go to the order detail page, I use the “Assign Barcode” scanner section at the top to scan that unassigned barcode, and then assign it to the specific order by saving the barcode number in the assignedBarcode field.

Up to this point, everything works fine.

The problem arises in the final step:
On the same order detail page, when I tap “Print Ticket,” the app fetches the order from Firebase, retrieves the assignedBarcode value, and should convert that into a barcode image to display it as part of the printed ticket.

This works perfectly in the iOS simulator, on Android physical devices, and even in other environments. But when I try it on a real iPhone, the barcode prints distorted from the thermal printer.

Gemini suggests that this is because real iPhones have much higher screen resolutions, and the barcode image ends up with pixel dimensions that the printer can’t handle properly — hence the distorted output.

I’ve tried everything to solve this, but no luck so far.
This process shouldn’t be so complicated, but I feel like I’ve made it messier somehow.

If anyone can help me out with this, I would truly appreciate it.

what packages do you use for this barcode generation and thermal printing?

I faced a similar issue before, and here’s how I solved it:

Instead of directly generating a barcode image with custom dimensions, I built the entire layout (including the barcode) using regular Flutter widgets. Then, I used the screenshot package to capture that widget as an image. Finally, I sent the captured image to the thermal printer.

This approach worked flawlessly — the barcode printed correctly on all devices, including real iPhones.

Screenshot was my next suggestion, you can make it easily without a package.

pixelRatio can losslessly scale up the resulting picture data, you should scale the preview widget to the screen, and scale the pixel ratio by that number too.

Image.memory(img, scale: 1), will display the result, you can scale this too to fit the screen, but you don’t have to display it

import 'dart:ui' as ui;

GlobalKey globalKey = GlobalKey();


  Future<Uint8List> _capturePng() async {
    final RenderRepaintBoundary boundary =
        globalKey.currentContext!.findRenderObject()! as RenderRepaintBoundary;
    final ui.Image image = await boundary.toImage(pixelRatio: 3.6);
    final ByteData? byteData = await image.toByteData(
      format: ui.ImageByteFormat.png,
    );
    return byteData!.buffer.asUint8List();
  }

----
Column(
        children: [
          RepaintBoundary(
              key: globalKey,
              child: Padding(
                padding: const EdgeInsets.all(16.0),
                // this is the preview
                child: const Text('Example Text! 😎',
                    style: TextStyle(color: Colors.deepPurple)),
              )),
          TextButton(
            onPressed: () async {
              Uint8List img = await _capturePng();
              if (context.mounted) {
                Navigator.of(context).push(
                  MaterialPageRoute(
                    builder: (context) => Result(img),
                  ),
                );
              }
            },
            child: const Text('Cheese'),
          ),
        ],
      )