Latest Results
chore(dicom-codec): raise jpeg-lossless-decoder-js to 2.2.1
@cornerstonejs/jpeg-lossless-decoder-js 2.2.1 restores the author metadata that
npm dropped from the published package: the manifest declared the author as an
array, which npm does not accept, so 2.2.0 carried no attribution at all. 2.2.1
is also the first version that CI published, so it carries a provenance
attestation, and 2.2.0 does not.
The decoded pixels cannot change. release/cjs/lossless.cjs and
release/cjs/lossless.cjs.map are byte-identical between 2.2.0 and 2.2.1, and
only README.md and package.json differ between the two tarballs.
Verified: the 102 dicom-codec tests pass, 7 skipped, including both byte-exact
JPEG Lossless comparisons.
pnpm-workspace.yaml needs no change. Its minimumReleaseAgeExclude entry names
the package and no version, so a new release of the package installs without an
edit here. A version-pinned entry, which is what pnpm writes by itself, would
have failed this install.
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>chore/jpeg-lossless-decoder-2.2.1 fix(dicom-codec): decode the last pixel of byte-aligned JPEG Lossless scans (#94)
Was previously approved by @jbocce, just updated to a published version of the jpeg lossless library from cs3d.
* fix(dicom-codec): decode the last pixel of byte-aligned JPEG Lossless scans
Published jpeg-lossless-decoder-js 2.1.2 drops the final sample of any frame
whose last Huffman code ends exactly on a byte boundary: its end-of-scan guards
read the 0xFF introducing EOI as entropy coded data and abandon the scan one
sample early. T.81 B.1.1.2 pads only an incomplete final byte, so a scan that
tiles its last byte exactly is legal and common - DCMTK emits one whenever a
frame ends in a run of a single value, which CT slices routinely do. Transfer
syntaxes 1.2.840.10008.1.2.4.57 and .70 decoded those frames with a wrong last
pixel.
The fix is upstream in cornerstonejs/JPEGLosslessDecoderJS (a fork of
rii-mango/JPEGLosslessDecoderJS) at 03bb80c0, which replaces the three
`index < markerIndex` guards with a named `readPastEntropyData` putting the
boundary at `index < 8`, and drops the `isLastPixel` special case that was
papering over the same off-by-one at one of the three sites.
That fork is not published to npm, so its CJS build is vendored under
src/vendor/jpeg-lossless-decoder-js (verbatim build output plus the MIT
LICENSE and a README recording the commit and how to re-vendor) and the
jpeg-lossless-decoder-js dependency is dropped. When a release carries the fix,
delete the directory and go back to a normal dependency.
Both JPEG Lossless fixtures now compare byte-for-byte against
CT-512x512.raw, replacing the it.fails pair that pinned the broken last
pixel. tools/fixture-verification agrees on both (12/12 byte-exact), as does
the vendored build's own suite (54 tests, including the regression fixture).
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
* refactor(dicom-codec): depend on the published fork, not a vendored build
The fix for transfer syntaxes 1.2.840.10008.1.2.4.57 and .70 lived only in the
cornerstonejs fork of jpeg-lossless-decoder-js, and the fork was not on npm, so
this repository committed a build of it under
packages/dicom-codec/src/vendor/. The fork now publishes as
@cornerstonejs/jpeg-lossless-decoder-js, so dicom-codec takes a normal
dependency and the vendored directory goes.
This answers all three review comments on the pull request:
- The vendor directory is removed, which is what the reviewer asked to happen
once the scoped package existed.
- README.md said the decoder was "built from the `main` branch". The branch
moves, so that sentence had a short life. It now names the published package.
- CodeRabbit read the fork's committed release/cjs/lossless.cjs at 03bb80c0 and
reported the vendored file as modified. The reviewer had already established
that the fork's committed artifact was the stale 2.1.2 build. The question
cannot arise again, because there is no vendored file.
The decoder bytes do not change. @cornerstonejs/jpeg-lossless-decoder-js@2.2.0
resolves to release/cjs/lossless.cjs, and that file is byte-identical to the
packages/dicom-codec/src/vendor/jpeg-lossless-decoder-js/lossless.cjs that this
commit deletes. The API shape is unchanged too: codecFactory looks up
`Decoder` on the module, and the package exports `Decoder` at the top level.
pnpm-workspace.yaml gains a minimumReleaseAgeExclude entry. pnpm refuses a
dependency version that the registry published very recently, and 2.2.0 is new.
The measure guards against third-party code, and this organisation publishes
this package, so waiting out the window would delay a decode fix and protect
nothing. The entry names the package and no version: pnpm writes a
version-pinned entry itself, and such an entry goes stale at every release of
the package.
Verified: the 102 dicom-codec tests pass, 7 skipped, including both byte-exact
JPEG Lossless comparisons — the .70 SV1 fixture is the regression case, and it
fails on any decoder without the fix. `pnpm csp:source` passes.
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
---------
Co-authored-by: Claude Opus 5 (1M context) <noreply@anthropic.com> refactor(dicom-codec): depend on the published fork, not a vendored build
The fix for transfer syntaxes 1.2.840.10008.1.2.4.57 and .70 lived only in the
cornerstonejs fork of jpeg-lossless-decoder-js, and the fork was not on npm, so
this repository committed a build of it under
packages/dicom-codec/src/vendor/. The fork now publishes as
@cornerstonejs/jpeg-lossless-decoder-js, so dicom-codec takes a normal
dependency and the vendored directory goes.
This answers all three review comments on the pull request:
- The vendor directory is removed, which is what the reviewer asked to happen
once the scoped package existed.
- README.md said the decoder was "built from the `main` branch". The branch
moves, so that sentence had a short life. It now names the published package.
- CodeRabbit read the fork's committed release/cjs/lossless.cjs at 03bb80c0 and
reported the vendored file as modified. The reviewer had already established
that the fork's committed artifact was the stale 2.1.2 build. The question
cannot arise again, because there is no vendored file.
The decoder bytes do not change. @cornerstonejs/jpeg-lossless-decoder-js@2.2.0
resolves to release/cjs/lossless.cjs, and that file is byte-identical to the
packages/dicom-codec/src/vendor/jpeg-lossless-decoder-js/lossless.cjs that this
commit deletes. The API shape is unchanged too: codecFactory looks up
`Decoder` on the module, and the package exports `Decoder` at the top level.
pnpm-workspace.yaml gains a minimumReleaseAgeExclude entry. pnpm refuses a
dependency version that the registry published very recently, and 2.2.0 is new.
The measure guards against third-party code, and this organisation publishes
this package, so waiting out the window would delay a decode fix and protect
nothing. The entry names the package and no version: pnpm writes a
version-pinned entry itself, and such an entry goes stale at every release of
the package.
Verified: the 102 dicom-codec tests pass, 7 skipped, including both byte-exact
JPEG Lossless comparisons — the .70 SV1 fixture is the regression case, and it
fails on any decoder without the fix. `pnpm csp:source` passes.
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>fix/jpeg-lossless-byte-aligned-end Latest Branches
+8%
chore/jpeg-lossless-decoder-2.2.1 -28%
fix/jpeg-lossless-byte-aligned-end +9%
test/codspeed-null-change © 2026 CodSpeed Technology