Browser Image Compression

Javascript module to be run in the web browser for image compression.
Features
- You can use this module to compress jpeg, png, webp, and bmp images by reducing resolution or storage size before uploading to the application server to save bandwidth.
- Multi-thread (web worker) non-blocking compression is supported through options.
Demo / Example
open https://donaldcwl.github.io/browser-image-compression/example/basic.html
or check the "example" folder in this repo
Usage
<input type="file" accept="image/*" onchange="handleImageUpload(event);">
async await syntax:
async function handleImageUpload(event) {
const imageFile = event.target.files[0];
console.log('originalFile instanceof Blob', imageFile instanceof Blob);
console.log(`originalFile size ${imageFile.size / 1024 / 1024} MB`);
const options = {
maxSizeMB: 1,
maxWidthOrHeight: 1920,
useWebWorker: true,
}
try {
const compressedFile = await imageCompression(imageFile, options);
console.log('compressedFile instanceof Blob', compressedFile instanceof Blob);
console.log(`compressedFile size ${compressedFile.size / 1024 / 1024} MB`);
await uploadToServer(compressedFile);
} catch (error) {
console.log(error);
}
}
Promise.then().catch() syntax:
Click to expand
function handleImageUpload(event) {
var imageFile = event.target.files[0];
console.log('originalFile instanceof Blob', imageFile instanceof Blob);
console.log(`originalFile size ${imageFile.size / 1024 / 1024} MB`);
var options = {
maxSizeMB: 1,
maxWidthOrHeight: 1920,
useWebWorker: true
}
imageCompression(imageFile, options)
.then(function (compressedFile) {
console.log('compressedFile instanceof Blob', compressedFile instanceof Blob);
console.log(`compressedFile size ${compressedFile.size / 1024 / 1024} MB`);
return uploadToServer(compressedFile);
})
.catch(function (error) {
console.log(error.message);
});
}
Installing
Use as ES module:
You can install it via npm or yarn
npm install browser-image-compression --save
yarn add browser-image-compression
import imageCompression from 'browser-image-compression';
(can be used in frameworks like React, Angular, Vue etc)
(work with bundlers like webpack and rollup)
(or) Load UMD js file:
You can download imageCompression from the dist folder.
Alternatively, you can use a CDN like delivrjs:
<script type="text/javascript" src="https://cdn.jsdelivr.net/npm/browser-image-compression@2.0.2/dist/browser-image-compression.js"></script>
Support
If this project helps you reduce the time to develop, you can buy me a cup of coffee :)

(powered by Stripe)
API
Main function
const options: Options = {
maxSizeMB: number,
maxWidthOrHeight: number,
onProgress: Function,
useWebWorker: boolean,
libURL: string,
preserveExif: boolean,
signal: AbortSignal,
maxIteration: number,
exifOrientation: number,
fileType: string,
initialQuality: number,
alwaysKeepResolution: boolean
}
imageCompression(file: File, options: Options): Promise<File>
Caveat
Each browser limits the maximum size of a browser Canvas object.
So, we resize the image to less than the maximum size that each browser restricts.
(However, the proportion/ratio of the image remains.)
Abort / Cancel Compression
To use this feature, please check the browser compatibility: https://caniuse.com/?search=AbortController
function handleImageUpload(event) {
var imageFile = event.target.files[0];
var controller = new AbortController();
var options = {
signal: controller.signal,
}
imageCompression(imageFile, options)
.then(function (compressedFile) {
return uploadToServer(compressedFile);
})
.catch(function (error) {
console.log(error.message);
});
setTimeout(function () {
controller.abort(new Error('I just want to stop'));
}, 1500);
}
Helper function
- for advanced users only, most users won't need to use the helper functions
imageCompression.getDataUrlFromFile(file: File): Promise<base64 encoded string>
imageCompression.getFilefromDataUrl(dataUrl: string, filename: string, lastModified?: number): Promise<File>
imageCompression.loadImage(url: string): Promise<HTMLImageElement>
imageCompression.drawImageInCanvas(img: HTMLImageElement, fileType?: string): HTMLCanvasElement | OffscreenCanvas
imageCompression.drawFileInCanvas(file: File, options?: Options): Promise<[ImageBitmap | HTMLImageElement, HTMLCanvasElement | OffscreenCanvas]>
imageCompression.canvasToFile(canvas: HTMLCanvasElement | OffscreenCanvas, fileType: string, fileName: string, fileLastModified: number, quality?: number): Promise<File>
imageCompression.getExifOrientation(file: File): Promise<number>
imageCompression.copyExifWithoutOrientation(copyExifFromFile: File, copyExifToFile: File): Promise<File>
Browsers support
| IE10, IE11, Edge | last 2 versions | last 2 versions | last 2 versions | last 2 versions | last 2 versions |
IE support
This library uses ES features such as Promise API, globalThis. If you need to support browsers that do not support new ES features like IE. You can include the core-js polyfill in your project.
You can include the following script to load the core-js polyfill:
<script src="https://cdnjs.cloudflare.com/ajax/libs/core-js/3.21.1/minified.min.js"></script>
Webp support
The webp compression is supported on major browsers. Please see https://caniuse.com/mdn-api_offscreencanvas_converttoblob_option_type_parameter_webp for browser compatibility.
The browser needs to support "OffscreenCanvas" API in order to take advantage of non-blocking compression. If the browser does not support "OffscreenCanvas" API, the main thread is used instead. See https://developer.mozilla.org/en-US/docs/Web/API/OffscreenCanvas#browser_compatibility for browser compatibility of "OffscreenCanvas" API.
Typescript type definitions
Typescript definitions are included in the package & referenced in the types section of the package.json
If your website has CSP enabled and you want to use Web Worker (useWebWorker: true), please add the following to the response header
content-security-policy: script-src 'self' blob: https://cdn.jsdelivr.net
blob: is for loading Web Worker script
https://cdn.jsdelivr.net is for importing this library from CDN inside Web Worker script. If you don't want to load this library from CDN, you can set your self hosted library URL in options.libURL.
Contribution
- fork the repo and git clone it
- run
npm run watch # it will watch code change in lib/ folder and generate js in dist/ folder
- add/update code in lib/ folder
- try the code by opening example/development.html which will load the js in dist/ folder
- add/update test in test/ folder
npm run test
- push to your forked repo on github
- make a pull request to dev branch of this repo