"use strict";
Object.defineProperty(exports, "__esModule", {
    value: true
});
Object.defineProperty(exports, "decodeQOI", {
    enumerable: true,
    get: function() {
        return decodeQOI;
    }
});
const QOI_OP_INDEX = 0x00;
const QOI_OP_DIFF = 0x40;
const QOI_OP_LUMA = 0x80;
const QOI_OP_RUN = 0xc0;
const QOI_OP_RGB = 0xfe;
const QOI_OP_RGBA = 0xff;
const QOI_MAGIC = 0x716f6966;
function hashColor(r, g, b, a) {
    return (r * 3 + g * 5 + b * 7 + a * 11) % 64;
}
function decodeQOI(buffer) {
    let pos = 0;
    if (buffer.length < 14) {
        throw new Error('Invalid QOI file: too short');
    }
    const magic = buffer.readUInt32BE(pos);
    pos += 4;
    if (magic !== QOI_MAGIC) {
        throw new Error(`Invalid QOI magic: expected ${QOI_MAGIC.toString(16)}, got ${magic.toString(16)}`);
    }
    const width = buffer.readUInt32BE(pos);
    pos += 4;
    const height = buffer.readUInt32BE(pos);
    pos += 4;
    const channels = buffer.readUInt8(pos);
    pos += 1;
    const colorspace = buffer.readUInt8(pos);
    pos += 1;
    if (channels !== 3 && channels !== 4) {
        throw new Error(`Invalid QOI channels: ${channels}`);
    }
    const pixelCount = width * height;
    const outputSize = pixelCount * 4;
    const output = Buffer.alloc(outputSize);
    const colorArray = new Array(64);
    for(let i = 0; i < 64; i++){
        colorArray[i] = [
            0,
            0,
            0,
            0
        ];
    }
    let r = 0, g = 0, b = 0, a = 255;
    let outPos = 0;
    while(outPos < outputSize){
        if (pos + 8 <= buffer.length) {
            let isEnd = true;
            for(let i = 0; i < 7; i++){
                if (buffer[pos + i] !== 0x00) {
                    isEnd = false;
                    break;
                }
            }
            if (isEnd && buffer[pos + 7] === 0x01) {
                break;
            }
        }
        if (pos >= buffer.length) {
            throw new Error('Unexpected end of QOI data');
        }
        const byte1 = buffer[pos++];
        if (byte1 === QOI_OP_RGB) {
            r = buffer[pos++];
            g = buffer[pos++];
            b = buffer[pos++];
        } else if (byte1 === QOI_OP_RGBA) {
            r = buffer[pos++];
            g = buffer[pos++];
            b = buffer[pos++];
            a = buffer[pos++];
        } else {
            const tag = byte1 & 0xc0;
            if (tag === QOI_OP_INDEX) {
                const index = byte1 & 0x3f;
                [r, g, b, a] = colorArray[index];
            } else if (tag === QOI_OP_DIFF) {
                const dr = (byte1 >> 4 & 0x03) - 2;
                const dg = (byte1 >> 2 & 0x03) - 2;
                const db = (byte1 & 0x03) - 2;
                r = r + dr & 0xff;
                g = g + dg & 0xff;
                b = b + db & 0xff;
            } else if (tag === QOI_OP_LUMA) {
                const byte2 = buffer[pos++];
                const dg = (byte1 & 0x3f) - 32;
                const dr_dg = (byte2 >> 4 & 0x0f) - 8;
                const db_dg = (byte2 & 0x0f) - 8;
                g = g + dg & 0xff;
                r = r + dg + dr_dg & 0xff;
                b = b + dg + db_dg & 0xff;
            } else if (tag === QOI_OP_RUN) {
                const run = (byte1 & 0x3f) + 1;
                for(let i = 0; i < run; i++){
                    output[outPos++] = r;
                    output[outPos++] = g;
                    output[outPos++] = b;
                    output[outPos++] = a;
                }
                const hash = hashColor(r, g, b, a);
                colorArray[hash] = [
                    r,
                    g,
                    b,
                    a
                ];
                continue;
            }
        }
        output[outPos++] = r;
        output[outPos++] = g;
        output[outPos++] = b;
        output[outPos++] = a;
        const hash = hashColor(r, g, b, a);
        colorArray[hash] = [
            r,
            g,
            b,
            a
        ];
    }
    return {
        width,
        height,
        channels,
        colorspace,
        data: output
    };
}

//# sourceMappingURL=qoi-decoder.js.map