UNPKG

codify-node

Version:

Generates 1D, 2D, and composite barcodes in png, svg, or eps formats.

119 lines (104 loc) 2.83 kB
import { PNG } from 'pngjs' import RGBAColor from '../types/RGBAColor' /** * Renders a PNG Blob stream to a base64 PNG. * * @param {PNG} png * @returns {Promise<string>} base64 representation */ function blobToBase64 (png: PNG): Promise<string> { const chunks: Uint8Array[] = [] return new Promise((resolve) => { png.pack() png.on('data', (c: Uint8Array) => chunks.push(c)) png.on('end', () => { const result = Buffer.concat(chunks) resolve('data:image/png;base64,' + result.toString('base64')) }) }) } /** * Writes the PNG instance to a buffer. * * @param {PNG} png - image instance * @returns {string} */ function getBuffer (png: PNG): Buffer { return PNG.sync.write(png) } /** * Converts the given hexadecimal number to RGBA. * * @param {string} hex - 6-digit or 8-digit RGB(A) representation in hex * @returns {RGBAColor} RGBA */ function getRgbaColor (hex = '000000FF'): RGBAColor { const colors = [ ...hex.match(/^([a-f\d]{2})([a-f\d]{2})([a-f\d]{2})([a-f\d]{2})?$/i) ?? [] ] const alpha = parseInt(colors[4], 16) if (colors.length >= 3) { return { red: parseInt(colors[1], 16), green: parseInt(colors[2], 16), blue: parseInt(colors[3], 16), alpha: !isNaN(alpha) ? alpha : 255 } } // default to solid black if color is invalid return { red: 0, green: 0, blue: 0, alpha: 255 } } /** * Returns true if two RGB colors are equal. * * @param {RGBAColor} a * @param {RGBAColor} b * @returns {boolean} */ function isEqualColor (a: RGBAColor, b: RGBAColor): boolean { return a.red === b.red && a.green === b.green && a.blue === b.blue } /** * Renders RGB 24 bitmap into an image instance of PNG * * @param {number[]} bitmap - containing RGB values * @param {number} width - width of bitmap * @param {number} height height of bitmap * @returns {PNG} instance of PNG */ function render (bitmap: number[], width: number, height: number, backgroundColor?: string, foregroundColor?: string): PNG { const png = new PNG({ width, height }) const backgroundColorRgba = getRgbaColor(backgroundColor) const foregroundColorRgba = getRgbaColor(foregroundColor) let i = 0 for (let y = 0; y < height; y++) { for (let x = 0; x < width; x++) { const color: RGBAColor = { red: bitmap[i], green: bitmap[i + 1], blue: bitmap[i + 2] } const rgba = isEqualColor(color, backgroundColorRgba) ? backgroundColorRgba : foregroundColorRgba const pos = (png.width * y + x) << 2 png.data[pos] = rgba.red png.data[pos + 1] = rgba.green png.data[pos + 2] = rgba.blue png.data[pos + 3] = rgba.alpha || 0 i += 3 } } return png } export default { blobToBase64, getBuffer, getRgbaColor, render }