Project Files
tests / pngText.test.cjs
const fs = require("node:fs");
const os = require("node:os");
const path = require("node:path");
const zlib = require("node:zlib");
const assert = require("node:assert/strict");
const { describe, it } = require("node:test");
const { parsePngTextAndZtxt } = require("../dist/pngText.js");
/** PNG CRC32 over *buf* (chunk type + chunk data). */
function crc32(buf) {
let c = -1 >>> 0;
for (let i = 0; i < buf.length; i++) {
c ^= buf[i];
for (let k = 0; k < 8; k++) c = (c >>> 1) ^ (0xedb88320 & -(c & 1));
}
return (c ^ -1) >>> 0;
}
/** Minimal 1x1 RGB PNG (IHDR + IDAT + IEND); insert ancillary chunks after IHDR (byte offset 33). */
function minimalRgbPngWithChunk(insertAfterIhdr) {
const minimal = Buffer.from(
"89504e470d0a1a0a0000000d4948445200000001000000010802000000907753de0000000c4944415408d763f8cfc000000301010018dd8db40000000049454e44ae426082",
"hex",
);
return Buffer.concat([minimal.subarray(0, 33), insertAfterIhdr, minimal.subarray(33)]);
}
describe("parsePngTextAndZtxt", () => {
it("returns empty for non-png", () => {
const dir = fs.mkdtempSync(path.join(os.tmpdir(), "lmexif-png-"));
const p = path.join(dir, "x.txt");
fs.writeFileSync(p, "not a png");
assert.deepEqual(parsePngTextAndZtxt(p), { tEXt: [], zTXt: [] });
});
it("decodes zTXt with zlib (not gzip)", () => {
const text = "hello-zTXt";
const comp = zlib.deflateSync(Buffer.from(text, "utf8"));
const chunkData = Buffer.concat([Buffer.from("Test\x00\x00", "binary"), comp]);
const type = Buffer.from("zTXt");
const crc = crc32(Buffer.concat([type, chunkData]));
const chunk = Buffer.alloc(4 + 4 + chunkData.length + 4);
chunk.writeUInt32BE(chunkData.length, 0);
type.copy(chunk, 4);
chunkData.copy(chunk, 8);
chunk.writeUInt32BE(crc, 8 + chunkData.length);
const dir = fs.mkdtempSync(path.join(os.tmpdir(), "lmexif-png-"));
const p = path.join(dir, "ztxt.png");
fs.writeFileSync(p, minimalRgbPngWithChunk(chunk));
const got = parsePngTextAndZtxt(p);
assert.equal(got.tEXt.length, 0);
assert.equal(got.zTXt.length, 1);
assert.equal(got.zTXt[0].keyword, "Test");
assert.equal(got.zTXt[0].text, text);
});
});