Skip to content

Add ImageInfo.CanDecode and UnsupportedImageFeatureException for PNG Adam7 interlacing - #18

Merged
Malcolmnixon merged 2 commits into
mainfrom
feature/candecode-unsupported-exception
Sep 25, 2026
Merged

Malcolmnixon merged 2 commits into
mainfrom
feature/candecode-unsupported-exception

Conversation

@Malcolmnixon

Copy link
Copy Markdown
Member

Summary

Implements Part 1 of the signed-off feedback-driven backlog (well-formed-but-unsupported PNG detection).

  • ImageInfo.CanDecode (init-only, default rue): reported by PngCodec.GetInfo as alse for Adam7-interlaced PNGs, letting a caller detect this before calling Load.
  • UnsupportedImageFeatureException (new, sealed class : IOException): thrown by PngCodec.Load instead of InvalidDataException for Adam7-interlaced files. Has a Feature string token ("png-adam7-interlace" for this case).

Why IOException and not InvalidDataException?

System.IO.InvalidDataException is sealed in .NET, so a new exception type cannot derive from it. UnsupportedImageFeatureException instead derives from IOException, InvalidDataException's own base class.

This is a deliberate, narrow, documented behavior change: an existing catch (InvalidDataException) around PngCodec.Load will no longer catch the Adam7-interlacing case. Callers that want to handle both malformed and well-formed-but-unsupported input together should catch IOException, or add an explicit catch (UnsupportedImageFeatureException).

Scope

Scoped to PNG only. Investigation across all four raster codecs (BMP/PNG/TIFF/JPEG) found Adam7 interlacing is the only case where a codec's Load refuses a file that is otherwise well-formed per its format's own specification; the others already conflate malformed/unsupported at GetInfo time.

Changes

  • src/DemaConsulting.CanvasNet/Codecs/ImageInfo.cs - CanDecode init-only property (outside the primary constructor, to avoid a binary-incompatible constructor/Deconstruct signature change).
  • src/DemaConsulting.CanvasNet/Codecs/UnsupportedImageFeatureException.cs (new).
  • src/DemaConsulting.CanvasNet/Codecs/PngCodec.cs - ParseIhdr/PngHeader carry InterlaceMethod; Load throws the new exception for Adam7; GetInfo sets CanDecode.
  • Tests: renamed/updated PngCodecTests.cs/PngSuiteTests.cs; new ImageInfoTests.cs and UnsupportedImageFeatureExceptionTests.cs.
  • Companion artifacts: reqstream (unit/subsystem/system level), design docs, verification docs, README, user guide, .reviewmark.yaml.

Testing

  • ./build.ps1: 3927/3927 tests passing (net8/9/10).
  • ./lint.ps1: clean (markdownlint, cspell, yamllint, dotnet format, reqstream, sysml2tools).

Co-authored-by: Copilot 223556219+Copilot@users.noreply.github.com

…Adam7 interlacing

Adds ImageInfo.CanDecode (init-only, default true) so GetInfo can report that a
well-formed file declares a feature Load cannot decode, without requiring a
caller to call Load and catch an exception just to find out. PNG is currently
the only codec where this applies: Adam7-interlaced files are well-formed PNG
per the specification, but PngCodec.Load has no interlaced-scanline
reconstruction logic.

Adds UnsupportedImageFeatureException, thrown by PngCodec.Load instead of
InvalidDataException for the Adam7 case, so callers can distinguish
well-formed-but-unsupported from malformed input without string-matching
Exception.Message. Because System.IO.InvalidDataException is sealed, this new
type derives from IOException (InvalidDataException's own base) instead - a
deliberate, documented behavior change: an existing catch (InvalidDataException)
around PngCodec.Load no longer catches the Adam7 case.

- ImageInfo.cs: add CanDecode as an init-only property outside the primary
  constructor, to avoid a binary-incompatible change to the record struct's
  generated constructor/Deconstruct signature.
- UnsupportedImageFeatureException.cs (new): sealed exception type with a
  Feature token identifying the specific unsupported feature.
- PngCodec.cs: ParseIhdr/PngHeader carry InterlaceMethod; Load throws
  UnsupportedImageFeatureException for Adam7; GetInfo sets CanDecode
  accordingly.
- Tests: renamed/added PngCodec and PngSuite tests for the new exception type
  and CanDecode; new ImageInfoTests.cs and
  UnsupportedImageFeatureExceptionTests.cs.
- Companion artifacts: reqstream/design/verification docs, README, user guide,
  and .reviewmark.yaml updated to match.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Copilot AI lite review requested due to automatic review settings September 25, 2026 22:40

Copilot AI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Copilot review overview

🟡 Changes recommended

Unresolved moderate issues remain in exception guidance and ImageInfo default-state behavior.

Get a fresh assessment by requesting another Copilot review.

Review effort: Lite
Findings: 5 Medium severity · 3 Low severity

Open (8)
What changed in this PR

Adds PNG Adam7 capability detection via ImageInfo.CanDecode and a dedicated unsupported-feature exception.

Changes:

  • Adds Adam7 detection and UnsupportedImageFeatureException.
  • Updates PNG tests and conformance expectations.
  • Updates documentation, requirements, verification, and traceability mappings.

Review identified unresolved API/documentation and default-value issues.

File Summary
test/​DemaConsulting.CanvasNet.Tests/​Codecs/​UnsupportedImageFeatureExceptionTests.cs Tests the new exception behavior.
test/​DemaConsulting.CanvasNet.Tests/​Codecs/​PngSuiteTests.cs Updates PNG conformance expectations.
test/​DemaConsulting.CanvasNet.Tests/​Codecs/​PngCodecTests.cs Tests Adam7 handling.
test/​DemaConsulting.CanvasNet.Tests/​Codecs/​ImageInfoTests.cs Tests CanDecode.
src/​DemaConsulting.CanvasNet/​Codecs/​UnsupportedImageFeatureException.cs Defines the unsupported-feature exception.
src/​DemaConsulting.CanvasNet/​Codecs/​PngCodec.cs Detects Adam7 and reports decode capability.
src/​DemaConsulting.CanvasNet/​Codecs/​ImageInfo.cs Adds decode-capability metadata.
README.md Documents pre-decode checks.
docs/​verification/​canvas-net/​codecs/​png-codec.md Updates PNG verification records.
docs/​user_guide/​introduction.md Documents API behavior and usage.
docs/​reqstream/​canvas-net/​codecs/​png-codec.yaml Updates PNG requirements.
docs/​reqstream/​canvas-net/​codecs.yaml Updates codec requirements.
docs/​reqstream/​canvas-net.yaml Updates system requirements.
docs/​design/​canvas-net/​codecs/​png-codec.md Updates PNG design details.
docs/​design/​canvas-net/​codecs.md Updates shared codec design guidance.
docs/​design/​canvas-net.md Updates public API design documentation.
.reviewmark.yaml Registers reviewed artifacts.

💡 Add a code-review agent skill or configure MCP servers for context-aware, tailored reviews. Learn more in the docs.

Comment thread docs/design/canvas-net/codecs.md Outdated
Comment thread docs/user_guide/introduction.md Outdated
Comment thread src/DemaConsulting.CanvasNet/Codecs/ImageInfo.cs
Comment thread src/DemaConsulting.CanvasNet/Codecs/UnsupportedImageFeatureException.cs Outdated
Comment thread README.md Outdated
Comment thread src/DemaConsulting.CanvasNet/Codecs/PngCodec.cs
Comment thread src/DemaConsulting.CanvasNet/Codecs/PngCodec.cs
…from review

- Correct the repeated claim that IOException is a common base for
  InvalidDataException and UnsupportedImageFeatureException: InvalidDataException
  derives directly from SystemException, not IOException. A caller that wants
  to handle both malformed (InvalidDataException) and well-formed-but-unsupported
  (UnsupportedImageFeatureException) cases together must add two explicit catch
  clauses, not a single catch (IOException). Fixed in
  UnsupportedImageFeatureException.cs, docs/design/canvas-net/codecs.md, and
  docs/user_guide/introduction.md.
- Document that default(ImageInfo) (or an uninitialized array element) has
  CanDecode == false, not true, because a struct's property initializers only
  run when a declared constructor runs; default(ImageInfo) zero-initializes
  every field directly. Added ImageInfoTests.ImageInfo_DefaultValue_HasCanDecodeFalse
  to cover this explicitly.
- PngCodec.cs: add the missing UnsupportedImageFeatureException documentation
  to the Load(string path) overload, and correct the validateDecodability
  parameter doc on the private ParseIhdr helper (said InvalidDataException,
  throws UnsupportedImageFeatureException).
- README.md: use the feature-and-message UnsupportedImageFeatureException
  constructor overload in the untrusted-file-triage example, so the example
  preserves the Feature token instead of discarding it.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Copilot AI review requested due to automatic review settings September 25, 2026 22:59

Copilot AI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@Malcolmnixon
Malcolmnixon merged commit 5feced7 into main Sep 25, 2026
7 checks passed
@Malcolmnixon
Malcolmnixon deleted the feature/candecode-unsupported-exception branch September 25, 2026 23:11
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.

2 participants