diff --git a/docs/adr/0005-image-filter-decoders.md b/docs/adr/0005-image-filter-decoders.md index 8bc7ec3..491c27d 100644 --- a/docs/adr/0005-image-filter-decoders.md +++ b/docs/adr/0005-image-filter-decoders.md @@ -71,6 +71,36 @@ and recorded, the way this repository treats every other file. there only when the specification allows it in an object stream, which `RunLengthDecode` and the four image codecs do not. +## Fixtures for the CCITT slice (2026-11-14) + +The next slice starts from data rather than from a description. Two strips and the bitmap they must produce +are committed beside the other image fixtures: + +- `tests/SharpCorePDF.Tests/Assets/ccitt/ccitt-g4.bin` — 26 bytes, Group 4, a 16 x 16 bilevel fixture + (a diagonal and a 6 x 6 block), written by Pillow 13.0.0 through libtiff. +- `ccitt-g3.bin` — the same bitmap as Group 3 one-dimensional, 68 bytes. +- `ccitt-expected.bin` — the 32 bytes Pillow decodes for that bitmap (`tobytes()`, 1 is white), rows padded + to a whole byte; the geometry is 16 x 16. + +They sit under `Assets/ccitt`, not `Assets/parity`, because `ParityCorpusTests` treats every file under +`Assets/parity` as a manifest entry. + +The generator is the one that produced `lzw-tiff-strip.bin`: `Image.save(format='TIFF', +compression='group4'|'group3')`, then a TIFF IFD read of `StripOffsets` (273) and `StripByteCounts` (279). + +Two facts the first attempt established, so the next one does not rediscover them: + +1. **The raw bitmap and `tobytes()` are complements.** Pillow's TIFF states a photometric that makes the + decoded samples the inverse of the mode-`1` pixels, so a decoder that fills black runs with 1 matches + `ccitt-expected.txt` only under the matching `BlackIs1` value. +2. **A line may start with a zero-length white run.** The transition at position 0 is what a line that + starts black states; a decoder that records only transitions after the first pixel shifts the parity of + every later `b1`, and the Group 4 fixture then fails on its twelfth line (a vertical mode resolves to a + position left of the current one). The fix is to record every transition, including one at 0. + +The RunLength slice is shipped; the CCITT decoder is the open work, and the Group 4 fixture now decodes its +first twelve lines correctly against this data. + ## Status of the slices | Slice | State | diff --git a/tests/SharpCorePDF.Tests/Assets/ccitt/ccitt-expected.bin b/tests/SharpCorePDF.Tests/Assets/ccitt/ccitt-expected.bin new file mode 100644 index 0000000..880b418 --- /dev/null +++ b/tests/SharpCorePDF.Tests/Assets/ccitt/ccitt-expected.bin @@ -0,0 +1 @@ +ÿ¿ÿßÿïÿð?ð?ð?ð?ð?ð?ÿßÿïÿ÷ÿûÿýÿþ \ No newline at end of file diff --git a/tests/SharpCorePDF.Tests/Assets/ccitt/ccitt-g3.bin b/tests/SharpCorePDF.Tests/Assets/ccitt/ccitt-g3.bin new file mode 100644 index 0000000..46fc1e2 Binary files /dev/null and b/tests/SharpCorePDF.Tests/Assets/ccitt/ccitt-g3.bin differ diff --git a/tests/SharpCorePDF.Tests/Assets/ccitt/ccitt-g4.bin b/tests/SharpCorePDF.Tests/Assets/ccitt/ccitt-g4.bin new file mode 100644 index 0000000..0fb1978 Binary files /dev/null and b/tests/SharpCorePDF.Tests/Assets/ccitt/ccitt-g4.bin differ