npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2026 – Pkg Stats / Ryan Hefner

piculum

v0.1.3

Published

The piculum codec: designed data regions inside ordinary PNG images - define typed fields in a picture, fill them into a sealed record, decode them anywhere.

Downloads

530

Readme

piculum

The piculum codec. A piculum is a data dictionary you can draw: a designer defines the fields of a record - a date, a name, a phone number, a choice from a list, free text, a file - by painting them onto a picture, each with a caption and a measured capacity. Someone else opens that design as a form, fills it in, and gets back a PNG that is the record. The picture is the delivery mechanism: one file that is the schema, the entry form, the transport, and the storage, traveling anywhere a picture travels and decoding (with the right password) into the structured fields the designer defined.

Content is sealed with authenticated encryption (AES-256-GCM under a PBKDF2-SHA256 key). A wrong password or a tampered image doesn't produce plausible garbage - the seal refuses to open.

See piculum.com.

Install

npm install piculum

The main entry is dependency-free.

Entries

  • piculum - the codec: encode/decode, mask definitions (v1 + v2), carriers, framing, crypto primitives, capacity math. No dependencies; everything runs locally on the caller's machine.
  • piculum/render - visible-layer rasterizers (human-readable text, images, QR/barcodes, rich text). All render peers are optional at install time (so the codec entry stays a one-package install), but importing this entry needs qrcode and dompurify installed; @zumer/snapdom is only needed if you rasterize rich text (it is lazy-loaded at call time).
  • piculum/node - PNG pixel I/O for Node, backed by the optional pngjs peer. Browsers need nothing; in Node, install it once and the whole codec works:
npm install piculum pngjs
import { encodeMessage, decodePng } from 'piculum';
import { installNodePng } from 'piculum/node';

installNodePng(); // once, before any encode/decode

const { png } = await encodeMessage('hello from the server', 'password', 200, 200);
const text = await decodePng(png.blob, 'password'); // 'hello from the server'

The mask definition file (MDF)

The MDF is the data dictionary itself: a small JSON document declaring the record's layers - which are data fields, which are visible decoration - that parseMaskDef / validateMaskDef check and normalize. Layer geometry (the painted pixels) lives separately in the v2 mask format; the MDF is the pure schema half.

{
  "version": 1,
  "name": "contactInfo",                // optional; self-describing for distributed files
  "description": "A contact card.",     // optional
  "font": "monospace", "size": 12,      // defaults for human-readable layers
  "definitions": [
    { "label": "Caption", "type": "human-readable" },
    { "label": "Pic", "type": "image", "fit": "aspect" },
    { "label": "QR", "type": "qr", "ecc": "M" },
    {
      "label": "phone",
      "type": "piculum",                          // a data-carrying field
      "field": { "type": "phone", "placeholder": "e.g. 555-0100" },
      "defaultAlloc": { "amount": 64, "unit": "bytes" }
    }
  ]
}

Piculum (data) layers can carry a typed field schema - text, date, number, phone, email, zip, or choice, with optional caption, required, options, placeholder, and defaultValue - which drives the entry widget when the design is filled as a form. defaultAlloc is a design-time sizing hint (unit: usable bytes or exact px) for tools that auto-place a layer's pixels; painted pixels remain the real capacity, and the codec never consults it.

The normalizer strips unknown properties, with one deliberate escape hatch: an ext object (any JSON, on the file or on a definition) is round-tripped untouched, so applications can carry experimental data through validation without a schema change.

Rendering visible layers

The codec alone encodes and decodes every data layer - nothing below is needed for that. The piculum/render entry is for drawing the layers a person sees on the picture (none of it is recovered on decode). Importing the entry loads qrcode and dompurify, so install both alongside it:

npm install piculum qrcode dompurify

Then, for example, QR/barcode layers:

import { rasterizeQr } from 'piculum/render';

rasterizeQr(pixels, width, height, region, 'https://example.com', { ecc: 'M' });

Per rasterizer:

| Rasterizer | Draws | Extra install | | --- | --- | --- | | rasterizeText | auto-fit human-readable text | none | | rasterizeImage | a picture fitted into the region | none | | rasterizeQr | QR / Code 128 codes | qrcode | | rasterizeRichText | formatted HTML text | dompurify, plus @zumer/snapdom at call time |

(rasterizeText and rasterizeImage have no libraries of their own, but they ship in the same entry, so qrcode and dompurify still need to be present unless your bundler tree-shakes the unused rasterizers away.)

Runtime support

The codec is pure Web APIs (WebCrypto, CompressionStream, Blob) plus one pluggable step: PNG bytes <-> RGBA pixels (PngIO).

  • Browsers - works out of the box (canvas adapter, auto-detected). loadPixels accepts any image format the browser decodes.
  • Node >= 20 - install the pngjs peer and call installNodePng() from piculum/node (PNG-only, byte-exact). Verified by the package's test:node round-trip suite.
  • Other runtimes (Deno, Bun, Workers) - the primitives exist there; bring a PngIO adapter via setPngIO() (the pngjs adapter may work as-is where Node compatibility is offered - unverified).

The render entry is DOM-only.

License

MIT - Copyright (c) 2026 Jeff Slarve