You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
{{ message }}
Repository navigation
feat: JPEG 2000 codec and PDF JPXDecode support - #45
Adds a dependency-free, decode-only JPEG 2000 codec (Jpeg2000Codec) and wires it into the PDF renderer so the /JPXDecode image filter works.
Codec: ISO 15444-1 Part 1 — JP2 boxes (ihdr, bpcc, colr, pclr/cmap, cdef) and raw codestreams; tiles/tile-parts; all five progression orders with POC; precincts; code-block styles; EBCOT tier-1 with the MQ decoder; tier-2 packets with tag trees; 5/3 and 9/7 inverse DWT; RCT/ICT; subsampling; ROI max-shift; 1–16 bit and signed samples (output scaled to 8 bits). Part-2/HTJ2K and >4 colour channels fail closed with UnsupportedImageFeatureException; malformed input throws InvalidDataException; allocations and work are capped.
PDF: JPX images use the JP2 colour space unless /ColorSpace is given; /SMaskInData, /Decode, and JPX as an /SMask. Also adds a general /SMask path (previously unsupported for raw/DCT images).
Tests/docs: test-only encoder, codec, fixture (ImageMagick-generated) and PDF tests, plus hostile-input tests; decode-wide CPU budget and public Jpeg2000DecoderLimits; raw 1/2/4/8/16-bit sample support; SysML2, reqstream, design, verification, reviewmark, README/user guide updated.
Known limitations: ICC profiles reported but not applied; naive CMYK; /Mask//Matte unsupported; JPX must be the sole filter; no inline images; truncated tile data is rejected. Encoder and decoder share an author, so 5/3, RCT, bypass and ROI paths are verified only against the test encoder (MQ verified against the T.88 vector; 9/7 against real files, not committed).
Type of Change
Bug fix (non-breaking change which fixes an issue)
New feature (non-breaking change which adds functionality)
Breaking change (fix or feature that would cause existing functionality to not work as expected)
Documentation update
Code quality improvement
Related Issues
Closes #
Pre-Submission Checklist
Build and Test
Code builds successfully and all tests pass: pwsh ./build.ps1 (12,552 tests, 0 failed)
Code produces zero warnings
Code Quality
New code has appropriate XML documentation comments
Static analyzer warnings have been addressed
Quality Checks
All linters pass: pwsh ./lint.ps1 (no errors)
Testing
Added unit tests for new functionality
Updated existing tests if behavior changed
All tests follow the AAA (Arrange, Act, Assert) pattern
Test coverage is maintained or improved
Documentation
Updated README.md (if applicable)
Updated docs/ documentation (if applicable)
Added code examples for new features (if applicable)
Updated requirements.yaml (if applicable)
Additional Notes
Real-world smoke check against a local third-party PDF with 7 JPX streams (not committed) decoded correctly, and a mutation fuzz run produced only the two allowed exception types.
…rse DWT
Work packages 3-4: MQ and raw decoders, all code-block styles, ROI maxshift, 5/3 and 9/7 inverse wavelets.
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Tiles lost main-header POC entries; a tile-part POC now replaces the inherited list.
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Includes T.88 MQ vector, round trips for all Part 1 features, JP2 boxes and hostile-input tests.
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Add ImageMagick/OpenJPEG-generated fixtures from synthetic sources, exact-match
decode tests against PNG sources, a PDF JPXDecode test and a system integration
test, with requirement and verification links.
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Added independent real-encoder evidence (07ede83): fixtures generated with ImageMagick 7.1.2/OpenJPEG from synthetic images (no third-party content), decoded pixel-exact against the source (5/3+RCT, all five progression orders, layers, gray, alpha, 16-bit, raw codestream), plus a system-integration and a PDF-level test. Also verified locally (not committed, licenses unclear) against ~38 jpylyzer-test-files: pixel-exact vs OpenJPEG on Kakadu/OpenJPEG/GraphicsMagick/ERDAS/Sentinel files, +/-1-3 levels on sYCC files; everything OpenJPEG rejects we reject. Not independently covered: 9/7 from committed fixtures, tiles, precincts, PPM/PPT (test encoder only).
…; fix doc counts
Expose Jpeg2000Image.BitDepth and HasPalette; PdfDocument rejects an
Indexed /ColorSpace over non-8-bit samples and any /ColorSpace override
on JP2 data with its own palette. Correct ordinal, test count and
codecs verification list.
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
…validation
- Add Jpeg2000DecoderLimits enforced during header validation before allocation
- Single decode-wide progression budget, POC entry cap and covered-volume skipping
- Reject codestreams with missing tiles; validate bit-plane counts and segmentation symbols
- Treat four channels as CMYK only when CMYK or unspecified
- Narrow the Guard backstop; tests assert specific exception types
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
…es, tests
Unpack sub-byte and 16-bit samples through the shared sample path so soft masks of
any depth work, apply /Decode exactly to 1- and 3-channel JPEGs, and add CCITT and
Indexed /Decode regression tests.
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
…t, document budget calibration
The per-input-byte term already bounds hostile input; the absolute ceiling
only needs to exceed the work of any image the default sample limit admits.
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
cmap is not limited to palette images: a legal mapping with Type == 0 directly selects or reorders codestream components even when there is no pclr box. This early return ignores every mapping whenever the palette is absent, so Decode, Load, and GetInfo can report/render channels in the wrong order for direct component mappings. Apply the direct mappings (and reject a type-1 mapping without a palette) instead of bypassing the box.
GetInfo walks jp2h children incrementally instead of buffering the superbox;
the ICC colr payload is kept as a slice and copied once when the image is built.
Pin cmap-without-pclr being ignored.
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
These remarks say the JPX decode is bounded by the PDF dictionary's /Width and /Height, but the implementation deliberately does not use those entries as limits; JpxDecoderLimits only sets Surface.MaxDimension. This misstates the security boundary and should describe the renderer-wide dimension limits instead.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Pull Request
Description
Adds a dependency-free, decode-only JPEG 2000 codec (
Jpeg2000Codec) and wires it into the PDF renderer so the/JPXDecodeimage filter works.UnsupportedImageFeatureException; malformed input throwsInvalidDataException; allocations and work are capped./ColorSpaceis given;/SMaskInData,/Decode, and JPX as an/SMask. Also adds a general/SMaskpath (previously unsupported for raw/DCT images).Jpeg2000DecoderLimits; raw 1/2/4/8/16-bit sample support; SysML2, reqstream, design, verification, reviewmark, README/user guide updated.Known limitations: ICC profiles reported but not applied; naive CMYK;
/Mask//Matteunsupported; JPX must be the sole filter; no inline images; truncated tile data is rejected. Encoder and decoder share an author, so 5/3, RCT, bypass and ROI paths are verified only against the test encoder (MQ verified against the T.88 vector; 9/7 against real files, not committed).Type of Change
Related Issues
Closes #
Pre-Submission Checklist
Build and Test
pwsh ./build.ps1(12,552 tests, 0 failed)Code Quality
Quality Checks
pwsh ./lint.ps1(no errors)Testing
Documentation
Additional Notes
Real-world smoke check against a local third-party PDF with 7 JPX streams (not committed) decoded correctly, and a mutation fuzz run produced only the two allowed exception types.