Ionic 3:使用蓝牙打印机打印图像 [英] Ionic 3: Print image using Bluetooth printer

查看:22
本文介绍了Ionic 3:使用蓝牙打印机打印图像的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我目前正在努力使用我们的 Ionic3 应用程序.我似乎不知道如何使用 BT 打印机和蓝牙串行插件打印图像.打印文字就好了.

我们正在使用此文档(由我的前同事找到)测试 RPP02N-BU 打印机

而原文是:

解决方案

所以我终于成功了.我使用了部分代码:https://github.com/song940/node-escpos 和设法打印徽标,甚至居中.

以下代码在 TypeScript 中

我创建了 ESCPOSImage 类:

/*** RGB接口*/接口 IRGB {r:数字;g:数字;b:号码;一个号码;}/*** ESCPOS 图像*/出口类 ESCPOSImage {//数据私人数据:数字[] = [];//宽度私有宽度:数字 = 0;//高度私人高度:数字= 0;/*** 构造函数* @param 图片*/构造函数(图像:HTMLImageElement){//设置宽度this.width = image.width;//设置高度this.height = image.height;//获取图像上下文让 ctx = this.getContext(image);//获取数据this.data = this.getBitData(ctx);}/*** 获取位数据* @param ctx*/私人getBitData(ctx:CanvasRenderingContext2D):数字[] {//初始化结果让结果:数字[] = [];//迭代行for (let y = 0; y < this.height; y++) {//迭代列for (let x = 0; x < this.width; x++) {//获取像素让像素 = ctx.getImageData(x, y, 1, 1).data;//获取 rgb让 rgb = this.getRGB(pixel);//获取 rgb 值让值 = rgb.r + rgb.g + rgb.b;//将位添加到结果中结果.push(值 > 0 ? 0 : 1);}}//返回结果返回结果;}/*** 获取图像上下文* @param 图片*/私人getContext(图像:HTMLImageElement):CanvasRenderingContext2D {//创建画布var canvas = document.createElement('canvas');画布.宽度=图像.宽度;画布.高度=图像.高度;//设置上下文var context = canvas.getContext('2d');context.drawImage(图像, 0, 0);//返回上下文返回上下文;}/*** 获取 RGB* @param 像素*/私人getRGB(像素:任何):IRGB {//返回 RGB返回 {r:像素[0],g:像素[1],b:像素[2],一:像素[3]}}/*** 栅格化*/公共 toRaster() {//初始化结果让结果 = [];//获取宽度和高度让宽度 = this.width;让高度 = this.height;//N 块行让 n = Math.ceil(width/8);//迭代for (让 y = 0; y < 高度; y++) {for (让 x = 0; x < n; x++) {for (让 b = 0; b <8; b++) {让 i = x * 8 + b;如果(结果[y * n + x] === 未定义){结果[y * n + x] = 0;}让 c = x * 8 + b;如果(c <宽度){if (this.data[y * width + i]) {结果[y * n + x] += (0x80 >> (b & 0x7));}}}}}//返回结果返回 {数据:结果,宽度:n,高度:高度};}}

该类实现了 toRaster 方法,稍后在 ESCPOSPrinter 类中使用:

/*** ESCPOS 打印机*/出口类 ESCPOSPrinter {//缓冲私有缓冲区:缓冲区;/*** 构造函数* @param 缓冲区*/构造函数(缓冲区:缓冲区){//初始化缓冲区this.buffer = 缓冲区;}/*** 写缓冲区* @param 缓冲区*/私人写(缓冲区:缓冲区){this.buffer = Buffer.concat([this.buffer, buffer]);}/*** 打印光栅* @param 图片* @param 模式*/公共光栅(图像:ESCPOSImage,模式:字符串='正常'){//获取标题让标头 = COMMANDS.S_RASTER_N;//获取栅格让光栅 = image.toRaster();//设置对齐this.align('center');//写头this.write(new Buffer(header));this.write(new Buffer([raster.width, 0]));this.write(new Buffer([raster.height, 0]));//写入数据this.write(new Buffer(raster.data));}/*** 打印线*/公共 printLn() {this.write(new Buffer([COMMANDS.CTL_CR, COMMANDS.CTL_LF]));}/*** 对齐* @param 对齐 ['left', 'center', 'right']*/公共对齐(对齐:字符串='左'){//创建对齐字典常量对齐 = {['左']:COMMANDS.TXT_ALIGN_LT,['中心']:COMMANDS.TXT_ALIGN_CT,['对']:COMMANDS.TXT_ALIGN_RT}//写对齐this.write(new Buffer(alignments[alignment]));}/*** 获取缓冲区*/公共getBuffer():缓冲区{返回 this.buffer;}}

最后,一起使用:

//创建图像让图像 = 新图像();//设置数据image.src = options.logo.content;//创建 ESCPOS 图像让 escposImage = new ESCPOSImage(image);//初始化ESCPOS打印机让 escposPrinter = new ESCPOSPrinter(new Buffer([]));//打印图像escposPrinter.raster(escposImage);//并且还打印新行escposPrinter.printLn();//将数据分配给打印队列printData = Buffer.concat([escposPrinter.getBuffer(), printData]);

然后将数据分成数据包并使用蓝牙串行插件的写入方法发送.

如果您想了解这些命令:

TXT_ALIGN_LT: [0x1b, 0x61, 0x00],//左对齐TXT_ALIGN_CT: [0x1b, 0x61, 0x01],//居中TXT_ALIGN_RT: [0x1b, 0x61, 0x02],//右对齐S_RASTER_N: [0x1d, 0x76, 0x30, 0x00],//设置光栅图像正常大小CTL_LF: [0x0a],//打印和换行CTL_CR: [0x0d],//回车

希望这对某人有所帮助.干杯

I am currently struggling with our Ionic3 app. I can't seem to find out how to print an image using BT printer and Bluetooth Serial plugin. Printing text is just fine.

We are testing RPP02N-BU printer using this documentation (found by my ex-colleague) Driver Commands Documentation, but I can not get the

SELECT BIT IMAGE MODE

to work.

We first resize uploaded image to not exceed 300px and we convert it to Black and White. When printing, we iterate the image and create binary strings, which we then convert to bytes. Those bytes follow the SELECT BIT IMAGE MODE commands.

Our code (in TypeScript) is as follows:

/**
 * Image to printer command
 * @param image 
 */
public static getImagePrintData(image: HTMLImageElement): Buffer {
    // Initialize list of commands
    let command: number[] = [ 0x1b, 0x2a, 33, 255, 3 ];

    // Get image bytes
    let bytes = this.getImageBytes(image);

    // Add bytes to command
    bytes.forEach((byte) => command.push(byte));

    // Return command
    return new Buffer(command);
}

/**
 * Get image bytes
 * @param image 
 */
private static getImageBytes(image: HTMLImageElement): number[] {
    // Init result
    let result = [];

    // Create image padding
    let padding = this.getZeroBytePadding(image.width);

    // Get image context
    let ctx = this.getImageContext(image);

    // Iterate image pixels
    for (let y = 0; y < image.height; y++) {
        // Init row string
        let row = "";

        // Go through row of pixels
        for (let x = 0; x < image.width; x++) {
            // Get pixel
            let pixel = ctx.getImageData(x, y, 1, 1).data;

            // Get rgb value
            let rgbValue = pixel[0] + pixel[1] + pixel[2];

            // Add 0 or 1 based on value
            row = row + (rgbValue > 0 ? 0 : 1);
        }

        // Add padding
        row = row + padding;

        // Now we need to split the row into byte chunks
        let byteChunks = row.match(/.{1,8}/g);

        // Now add those byte chunks to result
        byteChunks.forEach((chunk) => result.push(parseInt(chunk, 2)));
    }

    // Return result
    return result;
}

/**
 * Get zero byte padding
 * @param value 
 */
private static getZeroBytePadding(value: number): string {
    // Init padding
    let padding = "";

    // Get difference
    let diff = value % 8;

    // Create padding
    for (let i = 0; i < (8 - diff); i++) {
        padding = padding + "0";
    }

    // Return result
    return padding;
}

/**
 * Get image context
 * @param image 
 */
private static getImageContext(image: HTMLImageElement): CanvasRenderingContext2D {
    // Prepare canvas to draw image into
    var canvas = document.createElement('canvas');
    canvas.width = image.width;
    canvas.height = image.height;

    // Context
    var ctx = canvas.getContext('2d');
    ctx.drawImage(image, 0, 0);

    return ctx;
}

Then the command is sent to BT printer:

// Initialize image
let image = new Image();
// Set data
image.src = options.logo.content;
// Get image print data
let imagePrintData = PrinterUtils.getImagePrintData(image);

// Push image to print queue
printQueue.push(this.bluetoothUtility.write(imagePrintData));

The resulting image looks like this:

And the original is:

解决方案

So I finally succeeded. I used parts of this code: https://github.com/song940/node-escpos and managed to print logo, even centered.

Following code is in TypeScript

I created ESCPOSImage class:

/**
 * RGB interface
 */
interface IRGB {
    r: number;
    g: number;
    b: number;
    a: number;
}

/**
 * ESCPOS image
 */
export class ESCPOSImage {

    // Data
    private data: number[] = [];

    // Width
    private width: number = 0;

    // Height
    private height: number = 0;

    /**
     * Constructor
     * @param image 
     */
    constructor(image: HTMLImageElement) {
        // Set width 
        this.width = image.width;

        // Set height
        this.height = image.height;

        // Get image context
        let ctx = this.getContext(image);

        // Get data
        this.data = this.getBitData(ctx);
    }

    /**
     * Get bit data
     * @param ctx 
     */
    private getBitData(ctx: CanvasRenderingContext2D): number[] {
        // Init result
        let result: number[] = [];

        // Iterate rows
        for (let y = 0; y < this.height; y++) {
            // Iterate columns
            for (let x = 0; x < this.width; x++) {
                // Get pixel
                let pixel = ctx.getImageData(x, y, 1, 1).data;

                // Get rgb
                let rgb = this.getRGB(pixel);

                // Get rgb value
                let value = rgb.r + rgb.g + rgb.b;

                // Add bit to result
                result.push(value > 0 ? 0 : 1);
            }
        }

        // Return result
        return result;
    }

    /**
     * Get image context
     * @param image 
     */
    private getContext(image: HTMLImageElement): CanvasRenderingContext2D {
        // Create canvas
        var canvas = document.createElement('canvas');
        canvas.width = image.width;
        canvas.height = image.height;

        // Set context
        var context = canvas.getContext('2d');
        context.drawImage(image, 0, 0);

        // Return context
        return context;
    }

    /**
     * Get RGB
     * @param pixel 
     */
    private getRGB(pixel: any): IRGB {
        // Return RGB
        return {
            r: pixel[0],
            g: pixel[1],
            b: pixel[2],
            a: pixel[3]
        }
    }

    /**
     * To raster
     */
    public toRaster() {
        // Init result
        let result = [];

        // Get width and height
        let width = this.width;
        let height = this.height;

        // N block lines
        let n = Math.ceil(width / 8);

        // Iterate
        for (let y = 0; y < height; y++) {
            for (let x = 0; x < n; x++) {
                for (let b = 0; b < 8; b++) {
                    let i = x * 8 + b;

                    if (result[y * n + x] === undefined) {
                        result[y * n + x] = 0;
                    }

                    let c = x * 8 + b;

                    if (c < width) {
                        if (this.data[y * width + i]) {
                            result[y * n + x] += (0x80 >> (b & 0x7));
                        }
                    }
                }
            }
        }

        // Return result
        return {
            data: result,
            width: n,
            height: height
        };
    }   
}

The class implements toRaster method, that is later used in ESCPOSPrinter class:

/**
 * ESCPOS printer
 */
export class ESCPOSPrinter {

    // Buffer
    private buffer: Buffer;

    /**
     * Constructor
     * @param buffer 
     */
    constructor(buffer: Buffer) {
        // Init buffer
        this.buffer = buffer;
    }

    /**
     * Write buffer
     * @param buffer 
     */
    private write(buffer: Buffer) {
        this.buffer = Buffer.concat([this.buffer, buffer]);
    }

    /**
     * Print raster
     * @param image 
     * @param mode 
     */
    public raster(image: ESCPOSImage, mode: string = 'normal') {
        // Get header
        let header = COMMANDS.S_RASTER_N;

        // Get raster
        let raster = image.toRaster();

        // Set alignment
        this.align('center');

        // Write header
        this.write(new Buffer(header));
        this.write(new Buffer([raster.width, 0]));
        this.write(new Buffer([raster.height, 0]));
        // Write data
        this.write(new Buffer(raster.data));
    }

    /**
     * Print line
     */
    public printLn() {
        this.write(new Buffer([COMMANDS.CTL_CR, COMMANDS.CTL_LF]));
    }

    /**
     * Align 
     * @param alignment ['left', 'center', 'right'] 
     */
    public align(alignment: string = 'left') {
        // Create alignment dictionary
        const aligments = {
            ['left']: COMMANDS.TXT_ALIGN_LT,
            ['center']: COMMANDS.TXT_ALIGN_CT,
            ['right']: COMMANDS.TXT_ALIGN_RT
        }

        // Write alignment
        this.write(new Buffer(aligments[alignment]));
    }

    /**
     * Get buffer
     */
    public getBuffer(): Buffer {
        return this.buffer;
    }
}

And finally, all together used:

// Create image
let image = new Image();

// Set data
image.src = options.logo.content;

// Create ESCPOS image
let escposImage = new ESCPOSImage(image);

// Initialize ESCPOS printer
let escposPrinter = new ESCPOSPrinter(new Buffer([]));

// Print image
escposPrinter.raster(escposImage);

// And also print new line
escposPrinter.printLn();

// Assign data to print queue
printData = Buffer.concat([escposPrinter.getBuffer(), printData]);

The data is then divided into packets and sent using write method of Bluetooth Serial plugin.

If you wonder about the commands:

TXT_ALIGN_LT: [0x1b, 0x61, 0x00],     // Left justification
TXT_ALIGN_CT: [0x1b, 0x61, 0x01],     // Centering
TXT_ALIGN_RT: [0x1b, 0x61, 0x02],     // Right justification

S_RASTER_N: [0x1d, 0x76, 0x30, 0x00], // Set raster image normal size

CTL_LF: [0x0a], // Print and line feed
CTL_CR: [0x0d], // Carriage return

Hope this helps someone. Cheers

这篇关于Ionic 3:使用蓝牙打印机打印图像的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆