packPNG v1.8 — JNG container support
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
.jngfile is parsed into
three sections (head / image / tail) and emitted as a.ppgwith a new
internal magic,TCIJ. Round-trip is byte-exact on the full sembiance JNG
corpus (8/8 samples covering grayscale, color, deflate-alphaIDAT,
JPEG-alphaJDAA, 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 useszstd-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 magicBuild-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
.ppgfiles decode under
v1.8 and vice versa. - v1.7e binaries fail cleanly with
bad TCIP magicon a.ppgproduced
from a JNG input (by design — old binaries can't reconstruct a JNG, so
refusing the file is safer than silently misparsing). - Legacy
.tcip/.ppgsarchives 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.jngfiles in-rmode.- 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@versionbumped to1.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 achcp 65001dance.
🤖 Generated with Claude Code