Issue / Use Case:
I am trying to print receipts that include Urdu text. The printer does not support Urdu characters natively, so I cannot print plain text.
Workaround:
- Design the receipt as a React Native View.
- Capture the View as a PNG using
react-native-view-shot.
- Convert the PNG to ESC/POS raster bytes.
- Send the bytes to a BLE thermal printer using
BleManager.write.
I would appreciate guidance or suggestions on the following:
- Optimizing BLE image printing:
Are there better ways to stream large ESC/POS raster images over BLE to reduce printing time?
- Efficient chunking / buffering strategies:
Is there a recommended way to split or buffer large byte arrays in react-native-ble-manager for faster printing?
- Alternative approaches:
Any suggestions for reliably printing non-ASCII text (like Urdu) on thermal printers without losing speed or quality?
- Best practices for ViewShot-to-ESC/POS workflow:
If others have experience printing captured views with BLE thermal printers, any performance tips would be very helpful.
Any help, code examples, or advice would be greatly appreciated!
Code Example:
import {Buffer} from 'buffer';
import {PNG} from 'pngjs/browser';
import BleManager from 'react-native-ble-manager';
import ViewShot from 'react-native-view-shot';
// Convert PNG base64 to ESC/POS raster bytes
const convertPngToEscPos = async (base64: string, targetWidth = 576) => {
const cleanBase64 = base64.replace(/^data:image\/\w+;base64,/, '');
const buffer = Buffer.from(cleanBase64, 'base64');
const png = PNG.sync.read(buffer);
const originalWidth = png.width;
const originalHeight = png.height;
const pixels = png.data;
const targetHeight = Math.floor((originalHeight * targetWidth) / originalWidth);
const bytesPerLine = Math.ceil(targetWidth / 8);
const imageBytes: number[] = [];
for (let y = 0; y < targetHeight; y++) {
for (let xByte = 0; xByte < bytesPerLine; xByte++) {
let byte = 0;
for (let bit = 0; bit < 8; bit++) {
const x = xByte * 8 + bit;
if (x >= targetWidth) continue;
const srcX = Math.floor((x * originalWidth) / targetWidth);
const srcY = Math.floor((y * originalHeight) / targetHeight);
const idx = (srcY * originalWidth + srcX) * 4;
const gray = 0.299 * pixels[idx] + 0.587 * pixels[idx+1] + 0.114 * pixels[idx+2];
const pixel = gray < 128 ? 1 : 0;
byte |= pixel << (7 - bit);
}
imageBytes.push(byte);
}
}
return {width: bytesPerLine, height: targetHeight, bytes: imageBytes};
};
// Sending to BLE printer
const handlePrint = async (printerId: string, serviceUUID: string, characteristicUUID: string, base64Image: string) => {
const {bytes, width, height} = await convertPngToEscPos(base64Image);
const dataToSend = [
0x1b, 0x40, // Initialize printer
0x1b, 0x33, 0x00, // Set line spacing
0x1d, 0x76, 0x30, 0x00,
width & 0xff,
(width >> 8) & 0xff,
height & 0xff,
(height >> 8) & 0xff,
...bytes,
0x1b, 0x64, 0x05, // Feed 5 lines
0x1d, 0x56, 0x00 // Cut
];
const chunkSize = 512;
for (let i = 0; i < dataToSend.length; i += chunkSize) {
const chunk = dataToSend.slice(i, i + chunkSize);
await BleManager.write(printerId, serviceUUID, characteristicUUID, chunk);
}
};
Issue / Use Case:
I am trying to print receipts that include Urdu text. The printer does not support Urdu characters natively, so I cannot print plain text.
Workaround:
react-native-view-shot.BleManager.write.I would appreciate guidance or suggestions on the following:
Are there better ways to stream large ESC/POS raster images over BLE to reduce printing time?
Is there a recommended way to split or buffer large byte arrays in
react-native-ble-managerfor faster printing?Any suggestions for reliably printing non-ASCII text (like Urdu) on thermal printers without losing speed or quality?
If others have experience printing captured views with BLE thermal printers, any performance tips would be very helpful.
Any help, code examples, or advice would be greatly appreciated!
Code Example: