Repository navigation
Decode progressive JPEG images - #29
Merged
Merged
Conversation
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
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
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.
What
DCTDecodenow reads progressive JPEG (SOF2) as well as baseline/extended (SOF0/SOF1): spectral selection and successive approximation accumulate in one quantised coefficient grid per component, and the inverse DCT runs once at the end. The DC first scan, the DC refinement, the AC first scan with EOB runs and ZRL, and the AC refinement with correction bits and new coefficients are all read; a non-interleaved AC scan (one component, its own block grid) and an interleaved DC scan land on the same blocks.Fixtures
Seven Pillow-written references under
tests/SharpCorePDF.Tests/Assets/jpeg/, each compared with Pillow's decode within two levels of every sample, plus a nine-point truncated-stream theory:jpeg-progressive.jpg— 32 x 32, quality 95, 4:4:4 (DC first, DC refine, AC first, AC refine)jpeg-progressive-420.jpg— 4:2:0 (interleaved DC with six blocks per MCU, non-interleaved chroma AC)jpeg-progressive-gray.jpg— one componentjpeg-progressive-cmyk.jpg— four components, plain CMYK (inverted output, as the baseline CMYK test does)jpeg-progressive-wide.jpg— 32 x 16, so the column and row block counts differjpeg-progressive-sparse.jpg— flat areas, so the EOB runs and the zero runs (ZRL) are usedjpeg-progressive-restart.jpg— a DRI interval and 150 restart markers, so the predictors and the EOB run resetThe last four were added after SonarCloud's new-code gate asked for them (see Mutation).
The two conventions that cost a round
An AC refinement scan reads the sign bit of a new coefficient before the correction bits of the coefficients the run passes over, and 1 means positive (0 negative) — the inverse of the magnitude field an AC first scan uses. Either backwards still decodes every scan and leaves a handful of coefficients one or two steps out, which is why the acceptance is the pixel comparison. Written down in ADR-005.
Mutation
Scoped reading of
Pdf/JpegDecoder.cs: 76.81% (710 killed + 2 timeouts, 127 survived, 88 no coverage, 1122 mutants; the new region — line 520 onwards — is 82.5%). The first reading, before the four coverage fixtures, was 70.23% with 72.0% in the new region; those fixtures killed the survivors it named (restart interval, sparse/ZRL, CMYK, non-square grid) and moved SonarCloud's new-code coverage from 78.35% (42 uncovered of 194) to 92.27% (15 uncovered of 194). What remains is the boundary and error end of the decoder — a DC difference that needs eleven bits, a coefficient exactly onSe, a DC refinement at Al > 0, the YCCK transform, a 4:2:2 or odd-sized image, a missing table, a budget boundary, and a few bit-reader branches. Recorded indocs/mutation-testing.md, not papered over.The reading was taken with a local 5.0.0 because 5.1.0 on this workstation ignores every form of scope: the
mutateentry instryker-config.json,--mutateand--since:mainall leave 23,042 mutants, and project mode is refused ("Test projects cannot be specified when running Stryker in solution context"). 5.0.0 project mode with the command-line--mutateapplies the filter (839 of 20,004). The pin and the workflow are unchanged; the note in the record has the evidence.Validation
dotnet build SharpCorePDF.slnx -c Release: 0 warnings, 0 errorsPdfJpegFilterTests: 24/24 (11 earlier + 4 progressive variants + 9 truncated-stream cases)net10.0andnet11.0