/* eslint-disable */ // @ts-nocheck function adler32(data) { let s1 = 0; let s2 = 0; for (const datum of data) { s1 = (s1 + datum) % 65521; s2 = (s2 + s1) % 65521; } return [s2 >> 8, s2 & 0xff, s1 >> 8, s1 & 0xff]; } function crc32(data) { const table = []; let crc = 0; for (let index = 0; index < 256; ++index) { crc = index; crc = crc & 1 ? 0xedb88320 ^ (crc >>> 1) : crc >>> 1; crc = crc & 1 ? 0xedb88320 ^ (crc >>> 1) : crc >>> 1; crc = crc & 1 ? 0xedb88320 ^ (crc >>> 1) : crc >>> 1; crc = crc & 1 ? 0xedb88320 ^ (crc >>> 1) : crc >>> 1; crc = crc & 1 ? 0xedb88320 ^ (crc >>> 1) : crc >>> 1; crc = crc & 1 ? 0xedb88320 ^ (crc >>> 1) : crc >>> 1; crc = crc & 1 ? 0xedb88320 ^ (crc >>> 1) : crc >>> 1; crc = crc & 1 ? 0xedb88320 ^ (crc >>> 1) : crc >>> 1; table[index] = crc; } crc = -1; for (const datum of data) { crc = (crc >>> 8) ^ table[(crc ^ datum) & 0xff]; } crc ^= -1; return [ (crc >> 24) & 0xff, (crc >> 16) & 0xff, (crc >> 8) & 0xff, crc & 0xff, ]; } function encode_png(canvas, width, channels) { const idat = []; const zlib = [0x78, 0x01]; const len = 1 + width * channels; const nlen = len ^ 0xffff; for (let line_begin = 0; canvas.length != line_begin; line_begin += width) { const line_end = line_begin + width; zlib.push( line_end === canvas.length ? 0x01 : 0x00, len & 0xff, (len >> 8) & 0xff, nlen & 0xff, (nlen >> 8) & 0xff ); idat.push(0x01); zlib.push(0x00); for (let position = line_begin; line_end !== position; ++position) { const pixel = canvas[position]; idat.push((pixel >> 24) & 0xff); zlib.push((pixel >> 24) & 0xff); idat.push((pixel >> 16) & 0xff); zlib.push((pixel >> 16) & 0xff); idat.push((pixel >> 8) & 0xff); zlib.push((pixel >> 8) & 0xff); if (channels === 4) { idat.push(pixel & 0xff); zlib.push(pixel & 0xff); } } } const height = canvas.length / width; return [137, 80, 78, 71, 13, 10, 26, 10].concat( encode_png_chunk("IHDR", [ (width >> 24) & 0xff, (width >> 16) & 0xff, (width >> 8) & 0xff, width & 0xff, (height >> 24) & 0xff, (height >> 16) & 0xff, (height >> 8) & 0xff, height & 0xff, 8, channels === 3 ? 2 : 6, 0, 0, 0, ]), encode_png_chunk("IDAT", zlib.concat(adler32(idat))), encode_png_chunk("IEND") ); } function encode_png_chunk(tag, data = []) { const { length } = data; const content = [ tag.charCodeAt(0), tag.charCodeAt(1), tag.charCodeAt(2), tag.charCodeAt(3), ].concat(data); return [ (length >> 24) & 0xff, (length >> 16) & 0xff, (length >> 8) & 0xff, length & 0xff, ].concat(content, crc32(content)); } function transcode_qoi_to_png(data) { if ( data.length < 22 || data[0] !== 0x71 || data[1] !== 0x6f || data[2] !== 0x69 || data[3] !== 0x66 ) { return; } const width = (data[4] << 24) | (data[5] << 16) | (data[6] << 8) | data[7]; const channels = data[12]; const colorspace = data[13]; if (channels !== 3 && channels !== 4 && colorspace !== 1) { return; } const length = data.length - 8; const canvas = []; const map = Array.from({ length: 64 }).fill(0x00000000); let pixel = 0x000000ff; let position = 14; while (position < length) { const byte = data[position]; const tag = byte >> 6; if (byte === 0xff) { // QOI_OP_RGBA const r = data[position + 1]; const g = data[position + 2]; const b = data[position + 3]; const a = data[position + 4]; position += 5; pixel = (r << 24) | (g << 16) | (b << 8) | a; map[(r * 3 + g * 5 + b * 7 + a * 11) % 64] = pixel; canvas.push(pixel); } else if (byte === 0xfe) { // QOI_OP_RGB const r = data[position + 1]; const g = data[position + 2]; const b = data[position + 3]; const a = pixel & 0xff; position += 4; pixel = (r << 24) | (g << 16) | (b << 8) | a; map[(r * 3 + g * 5 + b * 7 + a * 11) % 64] = pixel; canvas.push(pixel); } else if (tag === 0x00) { // QOI_OP_INDEX if ( data[position] === 0x00 && data[position + 1] === 0x00 && data[position + 2] === 0x00 && data[position + 3] === 0x00 && data[position + 4] === 0x00 && data[position + 5] === 0x00 && data[position + 6] === 0x00 && data[position + 7] === 0x01 ) { break; } position += 1; pixel = map[byte]; canvas.push(pixel); } else if (tag === 0x01) { // QOI_OP_DIFF const dr = ((byte >> 4) & 0x03) - 2; const dg = ((byte >> 2) & 0x03) - 2; const db = (byte & 0x03) - 2; const r = (((pixel >> 24) & 0xff) + dr) & 0xff; const g = (((pixel >> 16) & 0xff) + dg) & 0xff; const b = (((pixel >> 8) & 0xff) + db) & 0xff; const a = pixel & 0xff; position += 1; pixel = (r << 24) | (g << 16) | (b << 8) | a; map[(r * 3 + g * 5 + b * 7 + a * 11) % 64] = pixel; canvas.push(pixel); } else if (tag === 0x02) { // QOI_OP_DIFF const byte_2 = data[position + 1]; const dg = ((byte & 0x3f) - 32) & 0xff; const dr = (((byte_2 >> 4) & 0x0f) - 8 + dg) & 0xff; const db = ((byte_2 & 0x0f) - 8 + dg) & 0xff; const r = (((pixel >> 24) & 0xff) + dr) & 0xff; const g = (((pixel >> 16) & 0xff) + dg) & 0xff; const b = (((pixel >> 8) & 0xff) + db) & 0xff; const a = pixel & 0xff; position += 2; pixel = (r << 24) | (g << 16) | (b << 8) | a; map[(r * 3 + g * 5 + b * 7 + a * 11) % 64] = pixel; canvas.push(pixel); } else { // QOI_OP_RUN for (let count = (byte & 0x3f) + 1; count > 0; --count) { canvas.push(pixel); } position += 1; } } return encode_png(canvas, width, channels); } export const decodeQoi = (imgData) => Buffer.from(new Uint8Array(transcode_qoi_to_png(new Uint8Array(imgData))));