browser-image-compression

repository·master·Indexed 23 days ago

https://github.com/donaldcwl/browser-image-compression

A JavaScript module for compressing JPEG, PNG, WebP, and BMP images directly in the web browser to reduce bandwidth and storage size before server upload. It provides the imageCompression function to resize images or reduce file size based on maxSizeMB and maxWidthOrHeight options, with support for Web Workers, EXIF preservation, and a suite of utility methods for converting between Files, Data URLs, and Canvas elements.

Tokens
4.5K
Snippets
8
Records
14
Agent score
79%

What's inside browser-image-compression

  1. Install browser-image-compression

    master

    You can install the library via npm or yarn for use in modern JavaScript environments, frameworks (React, Angular, Vue, etc.), or with bundlers like webpack and rollup.

    Alternatively, you can load the UMD JS file directly via a CDN.

    npm install browser-image-compression --save
    # or
    yarn add browser-image-compression
    import imageCompression from 'browser-image-compression';
    <script type="text/javascript" src="https://cdn.jsdelivr.net/npm/browser-image-compression@2.0.2/dist/browser-image-compression.js"></script>
  2. Configure Content Security Policy (CSP) for Web Workers

    master

    If your website has a Content Security Policy (CSP) enabled and you want to use useWebWorker: true, you must add the following to your response header:

    content-security-policy: script-src 'self' blob: https://cdn.jsdelivr.net

    • blob: is required for loading the Web Worker script.
    • https://cdn.jsdelivr.net is required if you are importing the library from a CDN inside the Web Worker. If you prefer to host the library yourself, set the options.libURL to your self-hosted URL.
  3. Use imageCompression with async/await

    master

    The imageCompression function returns a Promise that resolves to a compressed File (which is an instance of Blob). You can use async/await syntax to handle the compression process and catch errors.

    async function handleImageUpload(event) {
    
      const imageFile = event.target.files[0];
      console.log('originalFile instanceof Blob', imageFile instanceof Blob); // true
      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); // true
        console.log(`compressedFile size ${compressedFile.size / 1024 / 1024} MB`); // smaller than maxSizeMB
    
        await uploadToServer(compressedFile); // write your own logic
      } catch (error) {
        console.log(error);
      }
    
    }
  4. Compress and upload an image using the sample frontend pattern

    master

    The following pattern demonstrates how to use browser-image-compression to compress a user-selected file and then upload the resulting blob to a server via a POST request using FormData.

    1. Use imageCompression(file, options) to compress the image.
    2. In the .then() callback, wrap the output in a FormData object.
    3. Use fetch with method: 'POST' to send the FormData to your API endpoint (e.g., http://localhost:3000/image-upload-api).
    <script src="https://cdn.jsdelivr.net/npm/promise-polyfill@8/dist/polyfill.min.js"></script>
    <script type="text/javascript" src="https://cdn.jsdelivr.net/npm/browser-image-compression@2.0.2/dist/browser-image-compression.js"></script>
    <input type="file" accept="image/*" onchange="compressImage(event);">
    <script>
        function compressImage (event) {
            const file = event.target.files[0]
            const options = {
                maxSizeMB: 1,
                maxWidthOrHeight: 1024,
            }
            imageCompression(file, options)
                .then(output => uploadToServer(output))
                .catch(err => console.error(err))
        }
    
        function uploadToServer (file) {
            const formData = new FormData()
            formData.append('image', file, file.name)
            const url = 'http://localhost:3000/image-upload-api'
            console.log('calling api', url, 'with data', Array.from(formData.entries())[0])
            return fetch(url, {
                method: 'POST',
                body: formData
            })
                .then(res => res.json())
                .then(body => console.log('got server response', body))
        }
    </script>
  5. Use imageCompression with Promise.then().catch()

    master

    If you prefer standard Promise syntax, you can use .then() to handle the successful compression and .catch() to handle errors.

    function handleImageUpload(event) {
    
      var imageFile = event.target.files[0];
      console.log('originalFile instanceof Blob', imageFile instanceof Blob); // true
      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); // true
          console.log(`compressedFile size ${compressedFile.size / 1024 / 1024} MB`); // smaller than maxSizeMB
    
          return uploadToServer(compressedFile); // write your own logic
        })
        .catch(function (error) {
          console.log(error.message);
        });
    }
  6. Abort or cancel compression

    master

    You can cancel an ongoing compression task by passing an AbortSignal from an AbortController into the options.signal property. This requires browser support for AbortController.

    function handleImageUpload(event) {
    
      var imageFile = event.target.files[0];
    
      var controller = new AbortController();
    
      var options = {
        // other options here
        signal: controller.signal,
      }
      imageCompression(imageFile, options)
        .then(function (compressedFile) {
          return uploadToServer(compressedFile); // write your own logic
        })
        .catch(function (error) {
          console.log(error.message); // output: I just want to stop
        });
      
      // simulate abort the compression after 1.5 seconds
      setTimeout(function () {
        controller.abort(new Error('I just want to stop'));
      }, 1500);
    }
  7. Configure imageCompression options

    master

    The imageCompression function accepts a File and an Options object. You must provide at least one of maxSizeMB or maxWidthOrHeight for compression to occur.

    Options Reference

    OptionTypeDescription
    maxSizeMBnumberTarget maximum size in MB (default: Number.POSITIVE_INFINITY).
    maxWidthOrHeightnumberScales down the image so width or height is $\le$ this value. Automatically respects browser Canvas limits (default: undefined).
    onProgressFunctionOptional callback receiving a progress percentage (0 to 100).
    useWebWorkerbooleanUse multi-thread web worker (default: true). Falls back to main-thread if OffscreenCanvas is unsupported.
    libURLstringURL of this library for importing script in Web Worker (default: https://cdn.jsdelivr.net/npm/browser-image-compression/dist/browser-image-compression.js).
    preserveExifbooleanPreserve Exif metadata for JPEG (e.g., Camera model) (default: false).
    signalAbortSignalUsed to abort/cancel the compression.
    maxIterationnumberMax number of compression iterations (default: 10).
    exifOrientationnumberOrientation value (see StackOverflow reference).
    fileTypestringOverride file type (e.g., 'image/jpeg') (default: file.type).
    initialQualitynumberInitial quality value between 0 and 1 (default: 1).
    alwaysKeepResolutionbooleanIf true, only reduces quality and keeps width/height (default: false).
    // you should provide one of maxSizeMB, maxWidthOrHeight in the options
    const options: Options = {
      maxSizeMB: 1,
      maxWidthOrHeight: 1920,
      useWebWorker: true,
      // ... other options
    }
    
    imageCompression(file: File, options: Options): Promise<File>
  8. Configure compression with Options

    master

    The Options object allows you to fine-tune the compression process.

    OptionTypeDefaultDescription
    maxSizeMBnumberNumber.POSITIVE_INFINITYTarget maximum file size in MB.
    maxWidthOrHeightnumberundefinedMaximum width or height for the output image.
    useWebWorkerbooleantrueWhether to use a Web Worker for compression.
    maxIterationnumber10Maximum number of compression iterations.
    exifOrientationnumber(from file exif)The exif orientation to use.
    onProgress(progress: number) => voidundefinedCallback function receiving progress from 0 to 100.
    fileTypestring(original mime type)The desired MIME type for the output file.
    initialQualitynumber1.0The initial quality setting.
    alwaysKeepResolutionbooleanfalseIf true, prevents resizing the image.
    signalAbortSignalundefinedAn AbortSignal to cancel the compression.
    preserveExifbooleanfalseWhether to preserve EXIF metadata.
    libURLstringhttps://cdn.jsdelivr.net/npm/browser-image-compression/dist/browser-image-compression.jsThe URL to load the library from if using workers.
  9. Advanced helper functions

    master

    The library exports several helper functions for advanced image manipulation tasks. Most users will only need the main imageCompression function.

    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>
  10. Browser support and IE polyfills

    master

    Browser Support

    • Edge/IE: Supports IE10, IE11, and Edge.
    • Firefox/Chrome/Safari/Opera: Supports the last 2 versions.
    • WebP: Supported on major browsers.

    IE Support (Polyfills)

    This library uses ES features like Promise and globalThis. If you need to support older browsers like IE, you must include a core-js polyfill:

    <script src="https://cdnjs.cloudflare.com/ajax/libs/core-js/3.21.1/minified.min.js"></script>

    Web Worker Support

    To use non-blocking compression via Web Workers, the browser must support the OffscreenCanvas API. If OffscreenCanvas is not supported, the library will fallback to running compression on the main thread.

  11. Use imageCompression utility methods

    master

    The imageCompression namespace provides several utility functions for working with files, data URLs, and canvas elements:

    • getDataUrlFromFile(file: File): Promise<string>: Converts a File to a Data URL.
    • getFilefromDataUrl(dataUrl: string, filename: string, lastModified?: number): Promise<File>: Converts a Data URL back into a File.
    • loadImage(src: string): Promise<HTMLImageElement>: Loads an image source into an HTMLImageElement.
    • drawImageInCanvas(img: HTMLImageElement, fileType?: string): HTMLCanvasElement: Draws an image into a canvas.
    • drawFileInCanvas(file: File, options?: Options): Promise<[ImageBitmap | HTMLImageElement, HTMLCanvasElement]>: Draws a file into a canvas and returns the image and the canvas.
    • canvasToFile(canvas: HTMLCanvasElement, fileType: string, fileName: string, fileLastModified: number, quality?: number): Promise<File>: Converts a canvas to a File.
    • getExifOrientation(file: File): Promise<number>: Retrieves the EXIF orientation from a file.