Skip to content

fix: preserve decoded image depth and indexed transparency - #276

Open
yeagoo wants to merge 3 commits into
VERT-sh:mainfrom
yeagoo:fix/image-depth-alpha
Open

fix: preserve decoded image depth and indexed transparency#276
yeagoo wants to merge 3 commits into
VERT-sh:mainfrom
yeagoo:fix/image-depth-alpha

Conversation

@yeagoo

@yeagoo yeagoo commented Sep 7, 2026

Copy link
Copy Markdown

The Q8 WASM engine can retain a 16-bit input depth tag even though its decoded channels are 8-bit. Writing that tag back produces unnecessarily high-depth output without recovering precision. Conversely, a low-bit palette PNG reports its index depth, which does not describe the precision of its RGB/alpha channels: a semi-transparent alpha value of 128 can become 85 in TIFF output. Indexed PNGs with transparency can also produce an unreadable PSD.

Bound output depth by Quantum.depth, with an 8-bit minimum for decoded channel values except valid packed TIFF samples, and expand indexed-alpha images to true-color alpha when writing PSD. The upper bound follows the engine's Quantum depth instead of hard-coding Q8. For low-depth TIFF/TIF output, inspect the actual channel precision before promoting the source depth. Valid 1/2/4-bit gray samples remain packed; palette colors and semi-transparent alpha that need 8 bits are still promoted. The precision scan only runs when writing TIFF from an image reporting fewer than 8 bits.

Validation

Real WASM round trips cover 16-bit-tagged PNG, low-bit indexed alpha and nontrivial palette colors across PNG, TIFF/TIF, JXL, JP2, PSD, PPM and WebP as applicable. Additional grayscale tests check 1/2/4-bit packed samples through both TIFF extensions. Pixel assertions compare against decoded Q8 inputs, not the original file's full 16-bit precision. AVIF's separate encoder compatibility fix is not required by this branch's tests.

  • bun run test: 28 passed, including five shared behavior tests.
  • The defect-focused tests fail against the unchanged upstream conversion function (12 failing tests before this fix).
  • bun run build: passed with a local .env based on .env.example.
  • ESLint and Prettier: changed files pass.
  • bun run check: the same 7 pre-existing missing Node type errors as upstream; no additional errors. Full-repository lint has existing failures outside this change; changed files pass.

Patch structure

This branch is based on upstream cc7b5a54d5e9c797b377db47b9bdfbb561707783 and includes shared test harness commit c69e961, which moves the existing magickConvert function unchanged into a utility imported by the worker. Tests invoke that exact production function with the installed WASM. No new package dependency is introduced.

Each repair branch can be reviewed independently. After the shared harness lands, the remaining branches will need rebasing onto upstream main to resolve overlapping edits in magick-convert.ts.

Shares the behavior-preserving test harness with #275.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant