Press n or j to go to the next uncovered block, b, p or k for the previous block.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 | 3x 1x 1x 1x 5x 1x 1x 1x 2x 7x 6x 6x 6x 5x 1x 2x 1x 1x 1x 1x 1x 2x 2x 2x 2x 2x 2x 2x 2x 2x 1x 3x | 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 } |