Skip to content

packPNG v1.8 — JNG container support

Choose a tag to compare

@YadeWira YadeWira released this 05 May 13:31
· 11 commits to master since this release

v1.8 — JNG (JPEG Network Graphics) container support

First release with JNG input support, plus a small build-system fix for
the kanzi Makefile target.

What's new

  • JNG inputs are recognised and processed. A .jng file is parsed into
    three sections (head / image / tail) and emitted as a .ppg with a new
    internal magic, TCIJ. Round-trip is byte-exact on the full sembiance JNG
    corpus (8/8 samples covering grayscale, color, deflate-alpha IDAT,
    JPEG-alpha JDAA, and progressive JPEG bitstreams).

  • Output stays .ppg. No new file extension was introduced. Inside the
    file, the 4-byte magic distinguishes content type:

    • TCIP — PNG/APNG (unchanged from v1.7e)
    • TCIJ — JNG (new in v1.8)
    • PPG1 / PPGS — legacy formats, still decode
  • Wire format (TCIJ v1): 4 B magic + 1 B version + 1 B flags + 2 B
    filename length + UTF-8 filename + three (raw_size, comp_size, bytes)
    sections. The image section uses zstd-19 --long=27; head and tail
    sections use plain zstd. Original chunk length / type / data / CRC bytes
    survive untouched, so byte-exact roundtrip is guaranteed regardless of how
    the source JNG was encoded.

Phase 1 vs Phase 2

This release ships the container parser + wrapper format only. The JDAT
chunks (the JPEG bitstream — typically the bulk of a JNG file) are stored
through zstd-19, which can't beat JPEG entropy. Compression on a mixed
corpus is therefore modest (≈ 90 % of original on a 70 KB sembiance batch);
small JNGs (< 2 KB) can grow slightly because the wrapper overhead exceeds
zstd savings on the head / tail.

Phase 2 (planned) will route JDAT through packJPG (already vendored in
the syc archiver), unlocking a ~25 % additional win on the JPEG portion. The
TCIJ format reserves a flags byte for that future content-type bit.

CLI

packPNG a image.jng              # → image.ppg     (TCIJ wrapper)
packPNG a -ver -dry image.jng    # round-trip verify in memory, no write
packPNG a -r -od out/ src/       # PNG/APNG/JNG inputs all dispatch correctly
packPNG x image.ppg              # decoder picks TCIP or TCIJ by magic

Build-system fix

The kanzi Makefile target now passes -DUSE_ZSTD and links -lzstd. This
is required for both the existing tovyCIP IDAT-passthrough path and the
new TCIJ wrapper. If you build manually, the recommended flag set is now:

-DUSE_KANZI -DUSE_ZSTD [-DUSE_LIBDEFLATE]
-lz -llzma -lzstd [-ldeflate] libkanzi.a -lpthread

Linux/Debian dependency: apt install libzstd-dev (already needed since
v1.6 in practice; the Makefile was just missing the flag).

Compatibility

  • PNG/APNG path unchanged from v1.7e. v1.7e .ppg files decode under
    v1.8 and vice versa.
  • v1.7e binaries fail cleanly with bad TCIP magic on a .ppg produced
    from a JNG input (by design — old binaries can't reconstruct a JNG, so
    refusing the file is safer than silently misparsing).
  • Legacy .tcip / .ppgs archives from v1.4–v1.6 still decode unchanged.

Bug fixes / housekeeping

  • Help text and banner subtitle updated to mention JNG (PNG/APNG/JNG …).
  • collect() recursion picks up .jng files in -r mode.
  • Legacy backends (-perfile / -m / -zstd / -fl2 / -kanzi / -kpng)
    reject JNG inputs cleanly with a one-line message instead of silently
    misrouting them — Phase 1 JNG support is wired exclusively through the
    default tovyCIP backend.
  • Manifest assemblyIdentity@version bumped to 1.8.0.0.

Binaries

  • packPNG-linux-x86_64-v1.8 — Linux x86-64, dynamically linked
    (zlib, liblzma, libzstd, libdeflate, libkanzi, pthread).
  • packPNG-windows-x86_64-full-v1.8.exe — Windows x86-64, statically
    linked, mingw-w64 cross-compiled. Includes the UTF-8 active-code-page
    manifest so non-ASCII filenames work without a chcp 65001 dance.

🤖 Generated with Claude Code