Skip to content
Merged
Show file tree
Hide file tree
Changes from 10 commits
Commits
Show all changes
46 commits
Select commit Hold shift + click to select a range
2bb332f
feat(jpeg2000): add codestream parsing, tile geometry and tier-2 pack…
Oct 10, 2026
d2f7552
feat(jpeg2000): add MQ/EBCOT tier-1 decoding, dequantization and inve…
Oct 10, 2026
861c384
feat(jpeg2000): add JP2 boxes, component transforms and public Jpeg20…
Oct 10, 2026
2310c7c
fix(jpeg2000): inherit main-header POC entries in tiles
Oct 10, 2026
1687c4d
test(jpeg2000): add test-only encoder and Jpeg2000Codec tests
Oct 10, 2026
66fd82a
feat(pdf): decode /JPXDecode image XObjects and /SMask soft masks
Oct 10, 2026
4a586c3
test(pdf): add JPXDecode and SMask PDF tests
Oct 10, 2026
5fc09b7
style(codecs): use US spellings in JPEG 2000 comments; update unsuppo…
Oct 10, 2026
c93b648
docs: add JPEG 2000 codec and PDF JPX requirements, design, verificat…
Oct 10, 2026
7e5736c
docs: use US spelling in reviewmark comment
Oct 10, 2026
07ede83
test(codecs): add real-encoder JPEG 2000 fixtures and tests
Oct 10, 2026
06a7ad1
fix(jpx): fail closed on Indexed non-8-bit and palette+ColorSpace JPX…
Oct 10, 2026
da13233
Harden JPEG 2000 decoder: decoder limits, decode-wide budget, strict …
Oct 10, 2026
5c2cc2c
Document JPEG 2000 decoder limits, budget and validation; add fixture…
Oct 10, 2026
245a427
Harden PDF image decoding: JPX limits, /SMask, shared /Decode, SMaskI…
Oct 10, 2026
9816ad5
Update docs, requirements and SysML for PDF image review fixes
Oct 10, 2026
93b342c
JPEG 2000: scale Tier-1 work budget with input and split precinct/pac…
Oct 10, 2026
20998d8
JPEG 2000: require full packet coverage and in-sequence tile-parts
Oct 10, 2026
729969b
JPEG 2000: rewrite hostile-limit tests to hit specific caps; add budg…
Oct 10, 2026
7ac913b
docs: JPEG 2000 budget, coverage, lenient behaviors, requirement test…
Oct 10, 2026
69be7fd
PDF images: support 1/2/4/8/16-bit samples, apply /Decode to DCT imag…
Oct 10, 2026
8564399
docs: PDF image bit depths, /Decode, soft masks, limits interface row
Oct 10, 2026
e7c6676
JPEG 2000: raise default MaxTier1Work to 2^34, add large lossless tes…
Oct 10, 2026
f1e5fc1
PDF images: add bit-depth tests, decode in place; docs cleanups
Oct 10, 2026
50e31d0
fix(jpeg2000): raise tier-1 per-byte allowance to 2^14, document host…
Oct 10, 2026
dfba39e
Fix lint: blank lines between members and wrap long design line
Oct 10, 2026
3b91d28
Reject COD/COC/QCD/QCC/RGN in later JPEG 2000 tile-parts
Oct 10, 2026
4706ece
Require /Subtype /Image on PDF /SMask streams
Oct 10, 2026
5809743
Validate JP2 signature content, reject signed palette columns, add PO…
Oct 10, 2026
6b7598f
Correct codec capability description in verification introduction
Oct 10, 2026
92dd35d
Fix JPEG 2000 SIZ tile-count overflow bypass
Oct 10, 2026
932bfa4
fix(jpeg2000): enforce exact payload lengths in marker and box parsers
Oct 10, 2026
ad69640
Use US spelling in JPEG 2000 user guide text
Oct 10, 2026
d5b1991
fix(jpeg2000): validate style-0 quantization entry counts, pin COC/QC…
Oct 10, 2026
e07a08d
test(jpeg2000): replace wall-clock assertions with deterministic deco…
Oct 10, 2026
ff2c8a9
refactor(jpeg2000): reduce cognitive complexity and parameter counts
Oct 10, 2026
6bdcd1e
test(pdf): restore original hang-guard values in unrelated PdfDocumen…
Oct 10, 2026
39caa8e
Jpeg2000: decode tiles in place without copying tile data
Oct 10, 2026
0be4a27
Correct codec docs for decode-only loaders and six-unit enumeration
Oct 10, 2026
b8e91d4
Jpeg2000: bound jp2h probing and avoid ICC profile copy
Oct 10, 2026
e2618b2
Add superbox to spell-check dictionary
Oct 10, 2026
71262e9
Jpeg2000: require ftyp, jp2h and ihdr (matching SIZ) in JP2 files
Oct 10, 2026
f25520c
Jpeg2000: enforce marker placement and reject duplicate PPM/PPT index…
Oct 10, 2026
e669936
Jpeg2000: add validation audit tests and consolidated validation table
Oct 10, 2026
f226112
Use US spelling gray in JPEG 2000 docs and comments
Oct 10, 2026
70697bd
Correct JPX dimension-limit documentation
Oct 10, 2026
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
58 changes: 58 additions & 0 deletions .cspell.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,64 @@ language: en

# Project-specific technical terms and tool names
words:
- bitplanes
- bitstream
- Cdef
- codestreams
- coef
- Colr
- CPRL
- csiz
- dequantization
- Dmax
- Dmin
- dplanes
- EBCOT
- fplane
- INITDEC
- INITENC
- Ippm
- Irrev
- isot
- Lblock
- LRCP
- lsot
- luts
- Mallat
- mant
- Memberwise
- NLPS
- NMPS
- Nppm
- Osiz
- Pclr
- Pcoc
- PCRL
- Prec
- Psot
- pterm
- Renorm
- RLCP
- RPCL
- rsiz
- scoc
- scod
- segsym
- signedness
- smask
- ssiz
- subband
- Sycc
- Termall
- Tsiz
- vcausal
- vsum
- xmap
- xmaps
- Xsiz
- ymaps
- ysiz
- Zppm
- Aabb
- functiontype
- Poppler
Expand Down
22 changes: 22 additions & 0 deletions .reviewmark.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -254,6 +254,27 @@ reviews:
- "test/DemaConsulting.CanvasNet.Tests/Codecs/GifCodecTests.cs" # unit tests
- "test/DemaConsulting.CanvasNet.Tests/Codecs/GifFixtureTests.cs" # fixture conformance tests

# CanvasNet-Codecs-Jpeg2000Codec Review (one per unit)
- id: CanvasNet-Codecs-Jpeg2000Codec
title: Review that CanvasNet Codecs Jpeg2000Codec Implementation is Correct
context:
- "docs/design/canvas-net.md"
- "docs/reqstream/canvas-net.yaml"
- "docs/design/canvas-net/codecs.md"
- "docs/reqstream/canvas-net/codecs.yaml"
paths:
- "docs/reqstream/canvas-net/codecs/jpeg2000-codec.yaml" # unit requirements
- "docs/design/canvas-net/codecs/jpeg2000-codec.md" # unit design
- "docs/verification/canvas-net/codecs/jpeg2000-codec.md" # unit verification
- "src/DemaConsulting.CanvasNet/Codecs/Jpeg2000Codec.cs" # unit source (public API entry point)
- "src/DemaConsulting.CanvasNet/Codecs/Jpeg2000Image.cs" # unit source (public decoded-image result type)
- "src/DemaConsulting.CanvasNet/Codecs/Jpeg2000ColorSpace.cs" # unit source (public color-space enum)
- "src/DemaConsulting.CanvasNet/Codecs/Jpeg2000/**/*.cs" # unit source (partial-class implementation files)
- "src/DemaConsulting.CanvasNet/Codecs/ImageInfo.cs" # shared header-only probe result type
- "src/DemaConsulting.CanvasNet/Codecs/NamespaceDoc.cs" # Codecs namespace documentation
- "test/DemaConsulting.CanvasNet.Tests/Codecs/Jpeg2000CodecTests.cs" # unit tests
- "test/DemaConsulting.CanvasNet.Tests/Codecs/Jpeg2000TestEncoder*.cs" # test-only JPEG 2000 encoder

# CanvasNet-Geometry Review (one per subsystem)
- id: CanvasNet-Geometry
title: Review that CanvasNet Geometry Subsystem Implementation is Correct
Expand Down Expand Up @@ -770,6 +791,7 @@ reviews:
- "src/DemaConsulting.CanvasNet.Pdf/NamespaceDoc.cs" # Pdf namespace documentation
- "test/DemaConsulting.CanvasNet.Pdf.Tests/PdfDocumentTests.cs" # unit tests
- "test/DemaConsulting.CanvasNet.Pdf.Tests/PdfDocumentMeshShadingTests.cs" # mesh shading unit tests
- "test/DemaConsulting.CanvasNet.Pdf.Tests/PdfDocumentJpxTests.cs" # JPXDecode/SMask unit tests
- "test/DemaConsulting.CanvasNet.Pdf.Tests/PdfSystemIntegrationTests.cs" # integration tests
- "test/DemaConsulting.CanvasNet.Pdf.Tests/PdfFixtureTests.cs" # fixture conformance tests

Expand Down
3 changes: 2 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,7 @@ image operations using `Span<T>`, and supports independent-copy cropping for loa
- 🖨️ **TIFF Codec** - Load/save 8-bit RGB/RGBA/Grayscale TIFF files
- 🗜️ **JPEG Codec** - Load baseline/progressive; save baseline JPEG
- 🎞️ **GIF Codec** - Decode-only load of first GIF frame; `GetInfo` reports the true frame count
- 🖼️ **JPEG 2000 Codec** - Decode-only load of JP2 files and raw codestreams (Decode also exposes color space and alpha)
- 📐 **SVG Codec** - Rasterize a common SVG subset to a surface (`DemaConsulting.CanvasNet.Svg`)
- 📄 **PDF Document** - Open, inspect, and rasterize PDF pages with font substitution (`DemaConsulting.CanvasNet.Pdf`)
- 📊 **Chart Rendering** - Build and paint Bar/Column/Line/Area/Pie/Doughnut charts (`DemaConsulting.CanvasNet.Charts`)
Expand Down Expand Up @@ -88,7 +89,7 @@ PngCodec.Save(surface, "surface.png");
using var reloaded = PngCodec.Load("surface.png");
```

Open a PDF and render a page (BMP/TIFF/JPEG/GIF/SVG codecs, header-only probing, and
Open a PDF and render a page (BMP/TIFF/JPEG/GIF/JPEG 2000/SVG codecs, header-only probing, and
feature-detection all follow the same pattern):

```csharp
Expand Down
12 changes: 6 additions & 6 deletions docs/design/canvas-net-pdf.md
Original file line number Diff line number Diff line change
Expand Up @@ -47,9 +47,9 @@ size — but every filled/stroked path painted in solid opaque black, since no c
implemented yet. Phase 3 added real device color (`g`/`G`/`rg`/`RG`/`k`/`K`/`cs`/
`CS`/`sc`/`SC`/`scn`/`SCN`), a generalized `/Filter`/`/DecodeParms` stream-decoding pipeline
(`FlateDecode` plus PNG/TIFF predictor reversal), and image XObjects (`Do`: `DCTDecode` via the
`CanvasNet` system's `Codecs.JpegCodec`, or raw `DeviceGray`/`DeviceRGB`/`DeviceCMYK` 8-bit
samples, composited through the current transformation matrix). Phase 4 added real text/font
rendering: `BT`/`ET`/`Tc`/`Tw`/`Tz`/`TL`/`Tf`/`Tr`/`Ts`/`Td`/`TD`/`Tm`/`T*`/`Tj`/`'`/`"`/
`CanvasNet` system's `Codecs.JpegCodec`, `JPXDecode` via `Codecs.Jpeg2000Codec`, or raw
`DeviceGray`/`DeviceRGB`/`DeviceCMYK` 8-bit samples, composited through the current transformation matrix).
Phase 4 added real text/font rendering: `BT`/`ET`/`Tc`/`Tw`/`Tz`/`TL`/`Tf`/`Tr`/`Ts`/`Td`/`TD`/`Tm`/`T*`/`Tj`/`'`/`"`/
`TJ` resolve a simple `/Subtype /TrueType` font from the current page's `/Resources/Font`
dictionary (requiring an embedded `/FontDescriptor/FontFile2`, loaded via the `CanvasNet`
system's `Fonts.TrueTypeFont`), map each shown byte through its `/WinAnsiEncoding`/
Expand Down Expand Up @@ -106,8 +106,8 @@ Form XObject's `/BBox` is never used to clip its content and its `/Group` (trans
entry is never consulted, though the Form itself renders; `/ShadingType` values outside `2`-`7`
and `/FunctionType 4` (PostScript calculator) functions fail closed; the `sh` operator and general
path clipping (`W`/`W*`) are supported; no
`/SMask`/alpha compositing or transparency groups (every decoded image is treated as fully
opaque); no `JPXDecode` filter decoding (fails closed; `CCITTFaxDecode` - Group 4 (T.6 MMR) only -
`/Mask`/`/Matte` image masks or transparency groups (an explicit `/SMask` and JPEG 2000
alpha are applied); `JPXDecode` is decoded (`CCITTFaxDecode` - Group 4 (T.6 MMR) only -
is supported); `/Separation`/`/DeviceN`/`/CalGray`/`/Lab` color spaces remain unsupported and fail
closed; and an encrypted document using any security handler, crypt-filter method, `/V`/`/R`
combination other than the ones listed above, or whose correct password is not supplied, fails
Expand Down Expand Up @@ -335,7 +335,7 @@ crypt filter), `pdf-encrypted-r-{revision}`,
non-empty one is genuinely required), `pdf-encrypted-incorrect-password`,
`pdf-encrypted-password-non-ascii` (an R2-R4 password outside ASCII 0-127),
`pdf-colorspace-{name}` (`Separation`/`DeviceN`/`CalGray`/`Lab`), `pdf-colorspace-Pattern`,
`pdf-colorspace-ICCBased`, `pdf-filter-{name}` (`JPXDecode` and any other unrecognized filter),
`pdf-colorspace-ICCBased`, `pdf-filter-{name}` (any unrecognized filter),
`pdf-tiff-predictor-bitdepth-{n}`, `pdf-image-bitdepth-{n}`, `pdf-pattern-not-declared`,
`pdf-pattern-type-{n}`, `pdf-pattern-tile-too-large`, `pdf-shading-type-{n}`,
`pdf-shading-colorspace-{family}`, `pdf-functiontype-{n}`, `pdf-function-multiinput`,
Expand Down
39 changes: 29 additions & 10 deletions docs/design/canvas-net-pdf/pdf-document.md
Original file line number Diff line number Diff line change
Expand Up @@ -34,8 +34,8 @@ filter pipeline, image XObjects (Phase 3), and, as of Phase 4, real embedded-Tru
rendering: `g`/`G`/`rg`/`RG`/`k`/`K`/`cs`/`CS`/`sc`/`SC`/`scn`/`SCN` set the actual fill/stroke
color a path paints with; a generalized `/Filter`/`/DecodeParms` pipeline (`FlateDecode` plus
PNG/TIFF predictor reversal) decodes any stream, not only a page's own `/Contents`; `Do` decodes
and composites a `/Subtype /Image` XObject (`DCTDecode` via `Codecs.JpegCodec`, or raw
`DeviceGray`/`DeviceRGB`/`DeviceCMYK` 8-bit samples) through the current transformation matrix;
and composites a `/Subtype /Image` XObject (`DCTDecode` via `Codecs.JpegCodec`, `JPXDecode` via
`Codecs.Jpeg2000Codec`, or raw `DeviceGray`/`DeviceRGB`/`DeviceCMYK` 8-bit samples) through the current transformation matrix;
and `BT`/`ET`/`Tc`/`Tw`/`Tz`/`TL`/`Tf`/`Tr`/`Ts`/`Td`/`TD`/`Tm`/`T*`/`Tj`/`'`/`"`/`TJ` resolve a
simple (non-composite) TrueType font declared in the current page's `/Resources/Font`
dictionary, map each shown byte through that font's `/Encoding` to a Unicode codepoint, and paint
Expand Down Expand Up @@ -94,10 +94,10 @@ glyph under a clip mode fails closed); and no additional stream filters were add
no transparency groups; shading/tiling pattern fills were added (`/ShadingType 2`/`3`,
`/PatternType 1`/`2` — see _`/Pattern` Color Space (Shading and Tiling Patterns)_ below, reusing
the `/FunctionType 0` sampled-function evaluator originally landed as Phase 1 groundwork,
alongside new `/FunctionType 2`/`3` support), no `JPX` filter decoding (fails closed;
`LZWDecode`/`ASCII85Decode`/`ASCIIHexDecode`/`RunLengthDecode` are supported as of Phase 7, and
`CCITTFaxDecode` - Group 4 (T.6 MMR) only - is supported as of Phase 15, see below), and no
`/SMask`/alpha compositing (every decoded image is treated as fully opaque) — these
alongside new `/FunctionType 2`/`3` support), `JPXDecode` is decoded (see Image XObjects below; `LZWDecode`/`ASCII85Decode`/
`ASCIIHexDecode`/`RunLengthDecode` are supported as of Phase 7, and
`CCITTFaxDecode` - Group 4 (T.6 MMR) only - is supported as of Phase 15, see below), and
`/Mask`/`/Matte` image masks remain unsupported (an explicit `/SMask` soft mask is applied) — these
remain out of scope for this phase and are silently skipped (any other undefined keyword) or
explicitly rejected (unsupported color spaces/filters/fonts/encodings/render modes), per the
operator/exception taxonomy documented below; a later phase is expected to add transparency
Expand Down Expand Up @@ -698,8 +698,9 @@ its own distinguishable `Feature` token.
`Codecs/Png/PngCodec.Filtering.cs`'s `DefilterRow`/`Sub`/`Up`/`Average`/`Paeth`/Paeth-predictor
algorithm, since those methods are `private` in a different assembly and cannot be reused
directly). Any other filter name (including `DCTDecode`/`CCITTFaxDecode`, which `PdfDocument.Images.cs`
always detects and bypasses before calling this pipeline; and `JPXDecode`/`JBIG2Decode`/
`Crypt`, which remain out of scope) throws
always detects and bypasses before calling this pipeline; `JPXDecode` (handled by the dedicated JPX
path described below), and
`JBIG2Decode`/`Crypt`, which remain out of scope) throws
`Codecs.UnsupportedImageFeatureException`; a malformed `/Filter`/`/DecodeParms` shape, an
unrecognized `/Predictor` value, or malformed bytes for any of the five supported filters
(missing EOD marker, invalid/out-of-range code or character, truncated run, or an out-of-range
Expand All @@ -725,8 +726,26 @@ its own distinguishable `Feature` token.
`ColorFromComponents`; an `/Indexed` sample is passed through `SamplesToColor` as a raw,
un-normalized palette index rather than divided by `255.0` like every other color space) and
`/BitsPerComponent` (`8` only — anything else throws
`Codecs.UnsupportedImageFeatureException`); `/SMask`/`/Mask` are never consulted (every decoded
image is treated as fully opaque, a documented Phase 3 limitation).
`Codecs.UnsupportedImageFeatureException`). A bare `/Filter /JPXDecode` image is detected and
dispatched to `DecodeJpxImageXObject`, which decodes the stream via
`Codecs.Jpeg2000Codec.Decode(byte[])` (trusting the decoder's dimensions over `/Width`/`/Height`
and mapping any `Jpeg2000Codec` failure to the existing `InvalidDataException`/
`UnsupportedImageFeatureException` conventions); `JPXDecode` combined with any other filter
throws `InvalidDataException`. When `/ColorSpace` is absent the JP2's own color space is used
(gray, sRGB, CMYK, or by channel count; five or more channels need an explicit `/ColorSpace`
and otherwise throw `UnsupportedImageFeatureException`); when present, `/ColorSpace`
(`DeviceGray`/`DeviceRGB`/`DeviceCMYK`, `/Indexed`, `/ICCBased` by component count) overrides it
and its component count must equal the decoded color channel count
(`InvalidDataException` otherwise); an `/Indexed` override uses the decoded 8-bit samples as
indices. An optional `/Decode` array (`DecodeArray`, applied to JPX images only) remaps each
8-bit sample; a wrong-length or non-numeric array throws `InvalidDataException`.
`/SMaskInData` selects how the codestream's opacity channel is used: `0` ignores it, `1` applies
it as straight alpha, `2` un-premultiplies the color and then applies it; other values throw
`InvalidDataException`. An explicit `/SMask` image (any filter, including `JPXDecode`; decoded
through the same `DecodeImageSamples` path without nested masks) is nearest-neighbor resampled
to the base image and its luminance multiplies the base alpha (`ApplySoftMask`), taking
precedence over `/SMaskInData`; `/Mask` and `/Matte` are not consulted. Inline images (`BI`) are
not supported at all, which satisfies the PDF rule that `JPXDecode` is not permitted inline.
`CompositeImageOntoSurface` inverts the CTM (a non-invertible/degenerate CTM silently paints
nothing), computes the device-space bounding box of the transformed unit square, and for every
destination pixel in that box nearest-neighbor-samples the source image (`row = floor((1 - v) *
Expand Down
37 changes: 32 additions & 5 deletions docs/design/canvas-net.md
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,9 @@ DEMA Consulting best practices. The system consists of six implemented subsystem
`JpegCodec` (a common real-world subset of JPEG: baseline/progressive decode with
4:4:4/4:2:2/4:2:0 support, baseline 4:2:0 encode), and `GifCodec` (decode-only load of a GIF's
first image frame, including LZW decompression and deinterlacing, plus a `GetInfo` that reports
the file's true total frame count without resolving later frames into a `Surface`). See
the file's true total frame count without resolving later frames into a `Surface`), and
`Jpeg2000Codec` (decode-only JPEG 2000 Part 1 decoder for JP2 files and raw codestreams, also
exposing the decoded color space and opacity channel for PDF `/JPXDecode` images). See
_Codecs Subsystem Design_ (`codecs.md`).
- **Geometry subsystem** (namespace `DemaConsulting.CanvasNet.Geometry`, folder
`src/DemaConsulting.CanvasNet/Geometry/`, flat — no further nesting): vector-geometry
Expand Down Expand Up @@ -82,9 +84,9 @@ DEMA Consulting best practices. The system consists of six implemented subsystem

The `Codecs` subsystem depends on the `Canvas` subsystem's `Surface` unit (constructing surfaces
and reading/writing rows via `Surface.GetRowSpanBytes`); the `Canvas` subsystem has no dependency
on `Codecs` or on any other subsystem. Within the `Codecs` subsystem, its five units are flat and
mutually independent — none of `BmpCodec`, `PngCodec`, `TiffCodec`, `JpegCodec`, or `GifCodec`
depends on any other codec. Each codec also exposes a pair of `GetInfo(Stream)`/`GetInfo(string)` overloads
on `Codecs` or on any other subsystem. Within the `Codecs` subsystem, its six units are flat and
mutually independent — none of `BmpCodec`, `PngCodec`, `TiffCodec`, `JpegCodec`, `GifCodec`,
or `Jpeg2000Codec` depends on any other codec. Each codec also exposes a pair of `GetInfo(Stream)`/`GetInfo(string)` overloads
returning the shared `ImageInfo` record struct (width, height, channel count, and alpha presence)
without fully decoding pixel data and without enforcing `Surface.MaxDimension` (now a public
constant, so callers can perform this comparison themselves before ever calling `Load`) — except
Expand All @@ -97,7 +99,8 @@ pattern, and _Surface Unit Design_ (`canvas/surface.md`) for `MaxDimension`. See
_Surface Unit Design_ (`canvas/surface.md`), _BmpCodec Unit Design_
(`codecs/bmp-codec.md`), _PngCodec Unit Design_ (`codecs/png-codec.md`),
_TiffCodec Unit Design_ (`codecs/tiff-codec.md`), _JpegCodec Unit Design_
(`codecs/jpeg-codec.md`), and _GifCodec Unit Design_ (`codecs/gif-codec.md`) for each unit's
(`codecs/jpeg-codec.md`), _GifCodec Unit Design_ (`codecs/gif-codec.md`), and
_Jpeg2000Codec Unit Design_ (`codecs/jpeg2000-codec.md`) for each unit's
internal collaboration.

The `Geometry` subsystem's five units collaborate as follows: `PathBuilder` records raw drawing
Expand Down Expand Up @@ -239,6 +242,16 @@ The system exposes the following public API to external consumers:
`ImageInfo` record struct, additionally reporting the file's true total frame count; unlike
every other codec's `GetInfo`, this decodes the first frame's LZW-compressed pixel data to
validate `CanDecode` (but never resolves it into a rendered `Surface`).
- **Jpeg2000Codec.Load(Stream stream)** / **Jpeg2000Codec.Load(string path)**: Loads a `Surface` from a
JPEG 2000 (JP2 or raw codestream) stream or file (decode-only - no save support). Throws
`ArgumentNullException` for a null `stream`/`path`, `ArgumentException` for an empty `path`,
`FileNotFoundException` for a missing file, `InvalidDataException` for malformed data, and
`UnsupportedImageFeatureException` for valid but unsupported JPEG 2000 features.
- **Jpeg2000Codec.GetInfo(Stream stream)** / **Jpeg2000Codec.GetInfo(string path)**: Returns the shared
`ImageInfo` record struct from the container and SIZ header alone, without decoding pixels.
- **Jpeg2000Codec.Decode(Stream stream)** / **Jpeg2000Codec.Decode(byte[] data)**: Decodes to a
`Jpeg2000Image` exposing 8-bit color samples, color space, optional opacity samples and ICC
profile.
- **Rect(float x, float y, float width, float height)**: Constructor; an axis-aligned rectangle in
position-plus-size form. `Rect.Empty` is a static, publicly readable union-identity sentinel.
- **Rect.Union(Rect)** / **Rect.Union(Rect, Rect)**: Returns the smallest rectangle enclosing both
Expand Down Expand Up @@ -354,6 +367,9 @@ The system exposes the following public API to external consumers:
| `JpegCodec.Save(...)` | Inbound | Method call | `surface` non-null |
| `GifCodec.Load(...)` | Inbound/Outbound | Method call / `Surface` return | Valid GIF stream or path |
| `GifCodec.GetInfo(...)` | Inbound/Outbound | Method call / `ImageInfo` | Valid GIF stream or path |
| `Jpeg2000Codec.Load(...)` | Inbound/Outbound | Method call / `Surface` return | Valid JPEG 2000 stream/path |
| `Jpeg2000Codec.GetInfo(...)` | Inbound/Outbound | Method call / `ImageInfo` | Valid JPEG 2000 stream/path |
| `Jpeg2000Codec.Decode(...)` | Inbound/Outbound | Method call / `Jpeg2000Image` | Valid JPEG 2000 stream/bytes |
| `Rect.Union(...)` | Inbound/Outbound | Method call / `Rect` return | None |
| `Rect.Intersect(...)` | Inbound/Outbound | Method call / `Rect` return | None |
| `Rect.Transform(Matrix3x2)` | Inbound/Outbound | Method call / `Rect` return | None |
Expand Down Expand Up @@ -577,6 +593,17 @@ measures (IEC 62304 §5.3.3).
then scanning, without fully decoding, every subsequent frame's own block structure) without
ever resolving those later frames into a rendered `Surface`

**JPEG 2000 load path:**

1. **Input**: Method parameter `stream`/`path` (or `data` for `Decode`)
2. **Validation**: `ArgumentNullException` for null arguments, `ArgumentException` for an empty
`path`, `InvalidDataException` for malformed data, `UnsupportedImageFeatureException` for
unsupported features
3. **Processing**: Parses the JP2 boxes (if any) and codestream headers, decodes tier-2 packets and
tier-1 code-blocks, applies dequantization, the inverse wavelet and component transforms, and
scales samples to 8 bits
4. **Output**: A new `Surface` (`Load`) or a `Jpeg2000Image` (`Decode`)

**TrueType font load and glyph-query path:**

1. **Input**: A font stream or file path, followed by caller-supplied codepoints or glyph indices
Expand Down
Loading
Loading