png-chunk-text
Encode and decode PNG tEXt chunks for embedding uncompressed metadata in PNG images.
Repository Health
Technical Analysis
png-chunk-text is a minimal JavaScript library for creating and parsing PNG tEXt chunks — the standard PNG mechanism for embedding uncompressed textual metadata such as author, copyright, or custom application data directly inside an image file. It exposes two functions, encode and decode, that convert between plain keyword/value pairs and the raw Latin-1 byte layout the PNG specification requires for tEXt chunks.
The library is designed to be composed with png-chunks-extract and png-chunks-encode, which handle splitting a PNG file into its constituent chunks and reassembling them. Together these three modules let you read and write custom metadata on PNG images in Node.js or in the browser via Browserify, without pulling in a full image-processing toolkit.
What You Get
- encode(keyword, content) - Builds a tEXt chunk object (
{name: 'tEXt', data: Uint8Array}) from a keyword/value pair, validating Latin-1 encoding and PNG’s 79-character keyword limit. - decode(chunk) - Parses a raw tEXt chunk (or its
.databuffer) back into a{keyword, text}object. - Zero runtime dependencies - The entire implementation is two small, dependency-free files (
encode.js,decode.js). - Composable with png-chunks-extract/encode - Designed to slot into the same author’s chunk-splitting and chunk-reassembly libraries for a full read/write pipeline.
Common Use Cases
- Embedding image provenance - Storing author, license, or source-URL metadata inside a PNG so it travels with the file.
- Custom application metadata - Hiding structured app-specific data (e.g. generation parameters, IDs) inside a PNG’s tEXt chunk.
- Round-tripping metadata edits - Extracting existing chunks, adding or modifying a tEXt chunk, and re-encoding the PNG.
- Building PNG tooling - Serving as a low-level building block inside larger image-processing or steganography-adjacent utilities.
Under The Hood
Architecture png-chunk-text has a deliberately flat, two-module architecture: index.js re-exports encode.js and decode.js, each a single pure function with no shared state, no classes, and no internal abstraction layers. encode() walks the keyword and content strings character-by-code into a single Uint8Array separated by a NULL byte, matching the PNG tEXt chunk layout letter-for-letter; decode() reverses that walk by scanning bytes and toggling a naming flag on the first NULL. There is no dependency injection, no configuration, and no data flow beyond function arguments and return values — the library assumes its caller already has raw chunk bytes (typically from a sibling library like png-chunks-extract) and hands back either a chunk object or a parsed record. If the core PNG tEXt binary format changed, both encode.js and decode.js would need a synchronized rewrite, but the isolation between the two functions means nothing else in the module would break.
Tech Stack The project is pure, dependency-free JavaScript (package.json lists an empty dependencies object) targeting both Node.js and the browser via Browserify; the only devDependencies are the companion png-chunks-encode/png-chunks-extract libraries used in the test suite, plus tape for test assertions, tap-spec for readable test output, and standard for zero-config linting. There is no build step, transpiler, bundler config, or TypeScript — index.js is shipped and required as-is. No database, ORM, web framework, or deployment target applies; this is a leaf utility module consumed by other packages.
Code Quality
Testing lives in a single test.js file using tape, exercising the round-trip of encode → png-chunks-encode → png-chunks-extract → decode against a real test.png fixture, and asserting both keyword and text match on decode, including the “cutely picks .data for you” convenience path. There is no CI configuration (no .github/workflows) and no coverage tooling, but standard enforces consistent style and catches a class of errors via lint-on-test (npm test runs standard && node test.js). Error handling is explicit: encode() throws descriptive errors for non-Latin-1 characters, over-length keywords, and embedded NULL bytes, and decode() throws on invalid NULL characters in content — there are no swallowed exceptions or silent fallbacks. There are no type annotations (plain ES5-style JavaScript, no TypeScript, no JSDoc types), and naming is consistent and minimal throughout.
API Design png-chunk-text’s public API is about as small as a PNG-metadata library’s could be: two top-level functions, encode(keyword, content) and decode(chunk), each taking primitive arguments and returning a plain object — no classes to instantiate, no options object to configure, no async/Promise machinery for what is fundamentally synchronous byte manipulation. decode() is deliberately forgiving about its input shape, accepting either a raw Uint8Array/Buffer or a whole chunk object ({name, data}) and unwrapping it automatically, which removes a common friction point when chaining it directly onto output from png-chunks-extract. Error messages are specific and actionable (naming the exact offending keyword and the exact PNG-spec limit violated) rather than generic. This isn’t novel technology — it’s a straightforward, well-scoped implementation of one paragraph of the PNG specification — but the API’s small surface area and forgiving input handling make it pleasant to drop into a larger PNG-chunk pipeline.