Search code examples
javascriptnode.jsbase64pngzpl

Convert ZPL (Base64) in image (PNG)


I need to convert a ZPL file into an image. I already use the labelary web service, but I need a solution that is less dependent on an external application.

I am proceeding in the following way. I'm getting the base64 encoded part: eJzs281u4zYQAGAKLMCewmsPhfgaPWipPtIeVUC1GPiQYx6hr9FDgdL....rest of the code (Z64 encoded), which would be the image of the ZPL file, and I'm trying to convert this to a png image. I tried using the code below, but I get this error: Error: Could not find MIME for Buffer

const fs = require('fs');
var base64Img = require('base64-img');
var Jimp = require('jimp');

try{
    var data = fs.readFileSync('./test.zpl', 'base64')
} catch (err) {
    console.log(err);
}

var buffer = Buffer.from(data, 'base64');

Jimp.read(buffer).then(res => {
    return res
    .quality(50)
    .rotate(90)
    .resize(250,250)
    .writeAsync('out.png');
}).catch(err => {
    console.log(err);
});

I tried using this method too, but it generates a png image, but it cannot be processed by the image viewer.

const fs = require('fs');
var base64Img = require('base64-img');

try{
    var data = fs.readFileSync('./test.zpl', 'base64')
} catch (err) {
    console.log(err);
}

var buffer = Buffer.from(data, 'base64');

fs.writeFileSync("./out.png", buffer);

Grateful.


Solution

  • Since you are dealing with a GRF (which is a header-less 1-bit bitmap), you will need a png-writing library to create the image - pngjs is the usual one to pull in:

    const fs = require('fs'),
          zlib = require('zlib'),
          PNG = require('pngjs').PNG;
    
    
    let match = /(\d+),(\d+),(\d+),:Z64:([^:]+):/
                      .exec(fs.readFileSync('test.zpl', 'ascii'));
    let size = +match[1];
    let rowl = +match[3];
    let grf = zlib.inflateSync(Buffer.from(match[4], 'base64'));
    
    // These values are from the ^GF command
    const png = new PNG({
        width: rowl * 8,
        height: size / rowl,
        filterType: -1
    });
    
    let offs = 0;
    let data = png.data;
    for (let i = 0; i < size; i++) {
        let byte = grf[i];
        for (let bit = 0x80; bit; bit = bit >>> 1) {
            let bw = (bit & byte) ? 0 : 255; // black (0) or white (255)
            data[offs++] = bw;
            data[offs++] = bw;
            data[offs++] = bw;
            data[offs++] = 255;  // fully opaque
        }
    }
    
    png.pack().pipe(fs.createWriteStream('test.png'));
    

    That is from memory and some cut and paste of existing code, so there could be a typo...