import { buf } from "crc-32"; import { Buffer } from "buffer"; import type { ImageProcessor } from "./main"; export type PNGChunk = [ string, // name Buffer, // data number, // crc number];// offset export class PNGDecoder { stopped = false; repr: Buffer; req = 8; ptr = 8; constructor(private reader: ReadableStreamDefaultReader, private strict = true) { this.repr = Buffer.from([]); } async catchup() { while (this.repr.byteLength < this.req) { const chunk = await this.reader.read(); if (chunk.done) { this.stopped = true; if (this.strict) throw new Error(`Unexpected EOF, got ${this.repr.byteLength}, required ${this.req}, ${chunk.value}`); return; } this.repr = Buffer.concat([this.repr, chunk.value]); } } async *chunks() { while (true) { this.req += 8; // req length and name await this.catchup(); if (this.stopped) break; const length = this.repr.readUInt32BE(this.ptr); const name = this.repr.slice(this.ptr + 4, this.ptr + 8).toString(); this.ptr += 4; this.req += length + 4; // crc //await this.catchup(); const pos = this.ptr + length + 8; await this.catchup(); yield [name, this.repr.slice(this.ptr, this.ptr + length + 4), this.repr.readUInt32BE(this.ptr + length + 4), this.ptr] as PNGChunk; this.ptr += length + 8; await this.catchup(); if (this.stopped) break; if (name == 'IEND') break; } } async dtor() { //ugh } } export class SyncBufferWriter { cumul: Buffer[] = []; write(b: Buffer) { this.cumul.push(b); } getBuffer() { return Buffer.concat(this.cumul); } } export class PNGEncoder { // writer: WritableStreamDefaultWriter; constructor(private writer: SyncBufferWriter) { this.writer.write(Buffer.from([0x89, 0x50, 0x4E, 0x47, 0x0D, 0x0A, 0x1A, 0x0A])); } insertchunk(chunk: PNGChunk) { let b = Buffer.alloc(4); const buff = chunk[1]; b.writeInt32BE(buff.length - 4, 0); this.writer.write(b); // write length this.writer.write(buff); // chunk includes chunkname b = Buffer.alloc(4); b.writeInt32BE(buf(buff), 0); this.writer.write(b); console.log("finished inserting"); } async dtor() { //this.writer.releaseLock(); //await this.writer.close(); } } export const BufferWriteStream = () => { let b = Buffer.from([]); const ret = new WritableStream({ write(chunk) { b = Buffer.concat([b, chunk]); } }); return [ret, () => b] as [WritableStream, () => Buffer]; };