Avatar for the cornerstonejs user
cornerstonejs
codecs
BlogDocsChangelog

Performance History

Latest Results

Merge remote-tracking branch 'origin/main' into chore/jpeg-lossless-decoder-2.2.1
chore/jpeg-lossless-decoder-2.2.1
18 hours ago
feat(libjxl): JPEG recompression and progressive encoding (#97) * feat(libjxl): JPEG recompression and progressive encoding Adds embind methods for the JPEG XL JPEG Recompression transfer syntax (1.2.840.10008.1.2.4.111) and for progressive output: - JpegXLEncoder.getJpegBuffer() / encodeJpeg(): recompress a JPEG bitstream losslessly (JxlEncoderAddJPEGFrame with JPEG metadata stored). - JpegXLDecoder.decodeToJpeg() / getJpegBuffer(): rebuild the original JPEG bytes from the jbrd box (JxlDecoderSetJPEGBuffer). - JpegXLEncoder.setProgressive(): progressive DC + QPROGRESSIVE_AC for lossy, RESPONSIVE for lossless, as cjxl -p. dicom-codec: transcode() goes directly between .50 and .111 without a pixel decode, the .111 codec exposes recompressJpeg()/reconstructJpeg(), and JPEG XL encodes accept a `progressive` option. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * chore(dist-size): update the libjxl baseline for JPEG recompression The encoder now links libjxl's JPEG transcode path (JxlEncoderAddJPEGFrame and the JPEG metadata store), and the decoder links JPEG reconstruction. - jpegxlwasm_encode.wasm: 2550720 -> 2598167 raw (+1.86%), 927454 -> 946918 gzip (+2.10%) - jpegxlwasm_decode.wasm: 1090788 -> 1092412 raw (+0.15%), 377101 -> 377733 gzip (+0.17%) Sizes are from the dist-libjxl artifact of the PR CI build (emsdk 3.1.74). Only the libjxl entry changes. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * fix(libjxl): address review of JPEG recompression and progressive encoding - setProgressive now sets RESPONSIVE and QPROGRESSIVE_AC for every frame, the same as cjxl -p (it previously set PROGRESSIVE_DC for lossy frames). - encodeJpeg() consumes the JPEG buffer, so a reused encoder cannot recompress the previous frame; getJpegBuffer(0) throws. - decodeToJpeg() clears the JPEG buffer first, so a failed call does not leave the previous frame readable. - Document that getFrameInfo() describes encode() input only. - dicom-codec: size the WASM buffers in bytes, so non-byte typed-array views work; reject an empty frame; use copyFromWasm. - dicom-codec: the .50 <-> .111 transcode shortcuts return the same imageInfo shape as the pixel path. - dicom-codec: .111 -> .50 falls back to decode and encode when the stream has no JPEG reconstruction data. - dicom-codec: one shared encoder and decoder wrapper for all JPEG XL syntaxes, so each WASM module loads once; null for unused names. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> --------- Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
main
18 hours ago
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>
main
1 month ago
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
1 month ago

Latest Branches

CodSpeed Performance Gauge
+8%
chore(dicom-codec): raise jpeg-lossless-decoder-js to 2.2.1#96
19 hours ago
e368009
chore/jpeg-lossless-decoder-2.2.1
CodSpeed Performance Gauge
+10%
feat(libjxl): JPEG recompression and progressive encoding#97
7 days ago
060c972
feat/libjxl-jpeg-recompression
CodSpeed Performance Gauge
-28%
1 month ago
73b8e1f
fix/jpeg-lossless-byte-aligned-end
© 2026 CodSpeed Technology
Home Terms Privacy Docs