jpeg-js
jpeg-js is a pure JavaScript library designed for encoding and decoding JPEG images without relying on native binaries or external dependencies. This makes it suitable for various JavaScript environments, including Node.js and browsers (browser support was explicitly added in v0.4.0). It offers synchronous APIs for converting raw image data to the JPEG format and vice-versa, providing direct control over image processing. The current stable version is 0.4.4, released in June 2022. The project has a relatively slow release cadence, with the most recent updates focusing on bug fixes and minor feature enhancements. Its primary differentiating factor is its complete JavaScript implementation, beneficial for environments with strict dependency constraints or where native modules are problematic. However, a significant trade-off is its performance: it is a CPU-blocking library and is considerably slower than native alternatives like `sharp` or browser-native `Canvas API`, which is a crucial consideration for any performance-sensitive application.
Common errors
-
Error: Maximum resolution exceeded while decoding JPEG. (max: 100MP)
cause The input JPEG image's resolution exceeds the `maxResolutionInMP` limit set in the decode options (default 100MP).fixIncrease the `maxResolutionInMP` option in `jpeg.decode()` if you expect to handle larger images, e.g., `{ maxResolutionInMP: 200 }`. -
Error: Maximum memory usage exceeded while decoding JPEG. (max: 512MB)
cause The decoding process requires more memory than allowed by the `maxMemoryUsageInMB` limit (default 512MB).fixIncrease the `maxMemoryUsageInMB` option in `jpeg.decode()` if you have more memory available and expect to handle memory-intensive images, e.g., `{ maxMemoryUsageInMB: 1024 }`. -
ReferenceError: Buffer is not defined
cause The code is being executed in an environment where the Node.js `Buffer` global is not available (e.g., a pure browser environment without a polyfill) and `jpeg-js` attempts to use it.fixIf running in a browser, ensure you have a `Buffer` polyfill or set `useTArray: true` in the `jpeg.decode()` options to receive pixel data as `Uint8Array`. Upgrade to `jpeg-js@0.4.4` for improved error messaging. -
TypeError: jpeg.decode is not a function
cause This usually occurs when trying to use named import syntax (e.g., `import { decode } from 'jpeg-js';`) for a module that exports an object with properties, rather than named exports.fixUse the correct import syntax: `import * as jpeg from 'jpeg-js';` for ESM, then access `jpeg.decode()` or `jpeg.encode()`. For CommonJS, `const jpeg = require('jpeg-js');` is correct.
Warnings
- gotcha jpeg-js is a pure JavaScript, synchronous, and CPU-blocking library. It is significantly slower than native image processing libraries (e.g., `sharp` in Node.js or the native Canvas API in browsers). Using it for large images or in performance-critical applications can lead to application unresponsiveness.
- breaking The `new Buffer()` constructor is deprecated in Node.js (since v6.0.0) and can lead to security vulnerabilities. Earlier versions of `jpeg-js` (before v0.4.2) might have used this constructor internally or encouraged its use in examples.
- gotcha Since v0.4.0, `jpeg-js` introduced `maxResolutionInMP` and `maxMemoryUsageInMB` options to prevent Out Of Memory (OOM) errors when processing excessively large or malformed JPEGs. Decoding images exceeding these limits will throw an error.
- gotcha When running in environments without a global `Buffer` object (e.g., some browser setups or older Node.js versions without explicit polyfills), you might encounter `ReferenceError: Buffer is not defined`.
Install
-
npm install jpeg-js -
yarn add jpeg-js -
pnpm add jpeg-js
Imports
- jpeg
import jpeg from 'jpeg-js';
import * as jpeg from 'jpeg-js';
- jpeg.decode
import { decode } from 'jpeg-js';const jpeg = require('jpeg-js'); const decoded = jpeg.decode(buffer); - jpeg.encode
import { encode } from 'jpeg-js';const jpeg = require('jpeg-js'); const encoded = jpeg.encode(imageData, quality);
Quickstart
import * as fs from 'fs';
import * as jpeg from 'jpeg-js';
// --- Decoding JPEG ---
const jpegData = fs.readFileSync('path/to/your/image.jpg');
try {
const rawImageData = jpeg.decode(jpegData, {
useTArray: false, // Decode pixels into a Buffer (Node.js) or Uint8Array (browser)
formatAsRGBA: true,
maxResolutionInMP: 100, // Limit max resolution to prevent OOM errors
maxMemoryUsageInMB: 512 // Limit max memory to prevent OOM errors
});
console.log('Decoded image dimensions:', rawImageData.width, rawImageData.height);
// rawImageData.data is a Buffer (Node.js) or Uint8Array (browser) containing pixel data
} catch (error) {
console.error('Error decoding JPEG:', error.message);
}
// --- Encoding JPEG ---
const width = 320;
const height = 180;
// Allocate a Buffer for RGBA pixel data. JPEGs ignore the alpha channel.
const frameData = Buffer.alloc(width * height * 4);
let i = 0;
while (i < frameData.length) {
frameData[i++] = 0xff; // Red
frameData[i++] = 0x00; // Green
frameData[i++] = 0x00; // Blue
frameData[i++] = 0xff; // Alpha (ignored in JPEG)
}
const rawImageData = {
data: frameData,
width: width,
height: height
};
try {
const jpegImageData = jpeg.encode(rawImageData, 50); // Quality 0-100
fs.writeFileSync('output.jpg', jpegImageData.data);
console.log('JPEG encoded successfully to output.jpg');
} catch (error) {
console.error('Error encoding JPEG:', error.message);
}