JPEG Lossless Decoder for JavaScript
jpeg-lossless-decoder-js is a specialized JavaScript and TypeScript library designed to decode JPEG Lossless images, particularly those encountered within the DICOM standard. It specifically supports DICOM transfer syntaxes 1.2.840.10008.1.2.4.57 (JPEG Lossless, Nonhierarchical, Processes 14) and 1.2.840.10008.1.2.4.70 (JPEG Lossless, Nonhierarchical, Processes 14 Selection 1). The library is currently stable at version 2.1.2, with recent significant updates including modernization to TypeScript in version 2.1.0. While release cadence isn't strictly fixed, it receives updates for bug fixes and modernization. Its primary differentiation lies in its ability to handle these specific DICOM-related JPEG lossless formats, which are generally not supported by common JPEG decoders, making it a critical tool in medical imaging applications. It originated as a port from a Java implementation by Helmut Dersch.
Common errors
-
ReferenceError: jpeg is not defined
cause Attempting to use `jpeg.lossless.Decoder` in a browser environment without including the `lossless.js` script or in a Node/bundled environment without proper ESM/CommonJS import.fixFor browser script tag usage, ensure `lossless.js` (or `lossless-min.js`) is included before your script. For module-based environments, use `import { Decoder } from 'jpeg-lossless-decoder-js';` or `const { Decoder } = require('jpeg-lossless-decoder-js');`. -
TypeError: (0 , jpeg_lossless_decoder_js_1.Decoder) is not a constructor
cause This typically occurs in CommonJS environments when attempting to `require('jpeg-lossless-decoder-js')` and then directly calling it as a constructor, or when mixing default/named import syntax incorrectly.fixIn CommonJS, use `const { Decoder } = require('jpeg-lossless-decoder-js');`. In ESM, use `import { Decoder } from 'jpeg-lossless-decoder-js';`. -
Error: JPEG not lossless, SOF: 0xc0
cause The input buffer provided to `decompress` is a standard JPEG (e.g., Baseline DCT), not a JPEG Lossless stream (which uses SOF marker 0xC3 for Huffman lossless, or 0xC7 for progressive lossless, not 0xC0).fixVerify that the input `ArrayBuffer` or `Uint8Array` contains a JPEG Lossless byte stream, specifically one conforming to DICOM transfer syntaxes 1.2.840.10008.1.2.4.57 or 1.2.840.10008.1.2.4.70.
Warnings
- breaking Version 2.0.5 temporarily removed the global `jpeg` object, which was re-added in v2.0.6. Users relying on the global variable for browser usage directly via script tags might have experienced issues if they updated to v2.0.5 and then reverted or updated to v2.0.6.
- gotcha The library was modernized to TypeScript in v2.1.0. While this provides type safety, users migrating from older JavaScript versions might need to adjust their import statements or build configurations. The API surface itself remained largely consistent.
- gotcha The `decompress` method expects a `Uint8Array` or `ArrayBuffer` containing the JPEG Lossless byte stream. It's crucial that this data is a valid JPEG Lossless stream (specifically DICOM compliant) for successful decoding. Passing in generic or incorrect JPEG data will lead to errors.
Install
-
npm install jpeg-lossless-decoder-js -
yarn add jpeg-lossless-decoder-js -
pnpm add jpeg-lossless-decoder-js
Imports
- Decoder
import Decoder from 'jpeg-lossless-decoder-js';
import { Decoder } from 'jpeg-lossless-decoder-js'; - Decoder (CommonJS)
const Decoder = require('jpeg-lossless-decoder-js');const { Decoder } = require('jpeg-lossless-decoder-js'); - Global 'jpeg' object
var decoder = new jpeg.lossless.Decoder();
Quickstart
import { Decoder } from 'jpeg-lossless-decoder-js';
// A minimal, invalid JPEG Lossless header for demonstration purposes.
// In a real application, this buffer would come from a DICOM dataset.
// This is NOT a valid JPEG stream, but demonstrates API usage.
const dummyJpegLosslessBuffer = new Uint8Array([
0xFF, 0xD8, // SOI (Start of Image)
0xFF, 0xC3, // SOF_0 (Start Of Frame, Lossless, Huffman)
0x00, 0x11, // Length
0x08, // Sample Precision (8 bits)
0x00, 0x01, // Number of Lines (1)
0x00, 0x01, // Samples per Line (1)
0x01, // Number of Components (1)
0x01, // Component ID (1)
0x11, // Horizontal/Vertical Sampling Factor (1x1)
0x00, // Quantization Table Selector (unused for lossless)
0xFF, 0xDA, // SOS (Start Of Scan)
0x00, 0x08, // Length
0x01, // Number of components in scan
0x01, // Component selector
0x00, // DC entropy coding table selector
0x00, 0x00, // EOI (End of Image) - placeholder, not actual data
0xFF, 0xD9 // EOI (End Of Image)
]).buffer;
const decoder = new Decoder();
try {
// Attempt to decompress the (dummy) buffer.
// In a real scenario, this would be a valid JPEG Lossless byte stream.
const outputBuffer = decoder.decompress(dummyJpegLosslessBuffer);
console.log('Successfully initialized Decoder and attempted decompression.');
console.log('Output buffer size:', outputBuffer.byteLength, 'bytes');
} catch (error) {
console.error('Error during decompression (expected for dummy buffer):', error.message);
console.log('Ensure you provide a valid JPEG Lossless ArrayBuffer for actual decoding.');
}
// Example with offset and length (if only a part of a larger buffer is the JPEG data)
const largeBuffer = new ArrayBuffer(dummyJpegLosslessBuffer.byteLength + 100);
new Uint8Array(largeBuffer, 50, dummyJpegLosslessBuffer.byteLength).set(new Uint8Array(dummyJpegLosslessBuffer));
try {
const outputWithOffset = decoder.decompress(largeBuffer, 50, dummyJpegLosslessBuffer.byteLength);
console.log('Decompression with offset/length simulated.');
console.log('Output with offset buffer size:', outputWithOffset.byteLength, 'bytes');
} catch (error) {
console.error('Error during offset/length decompression (expected for dummy buffer):', error.message);
}