sharp

repository·main·Indexed 12 days ago

https://github.com/lovell/sharp

High-performance Node-API module for resizing and converting images in JPEG, PNG, WebP, GIF, AVIF, and TIFF formats. Leveraging libvips, it provides fast image processing capabilities including resizing, compositing, color space conversion, and channel manipulation for Node.js applications. Version 0.35.3.

Tokens
32.2K
Snippets
131
Records
225
Agent score
97%

What's inside sharp

  1. Join or animate an array of input images

    main

    Starting from version 0.34.0, sharp supports passing an array of input images to create joined images or animations. This replaces previous patterns for combining multiple image buffers or files into a single output.

    // Example pattern (conceptual based on v0.34.0 breaking change)
    // sharp([image1, image2, image3]).toFile('output.gif');
  2. Optimize parallelism and concurrency in sharp

    main

    Sharp's performance depends on two levels of concurrency: the number of images processed in parallel by Node.js, and the number of threads used to process each individual image via libvips.

    1. Increasing parallel image processing

    Node.js uses a libuv thread pool for asynchronous calls to native modules. By default, this pool size is 4. If you are using a machine with more than 4 physical CPU cores, you should increase UV_THREADPOOL_SIZE before starting your Node.js process to allow more images to be processed simultaneously.

    2. Managing threads per image

    libvips uses a shared thread pool that grows and shrinks on demand. By default, it uses one thread per CPU core. You can manually control this behavior using sharp.concurrency().

    3. Reducing memory fragmentation on Linux

    When using the default glibc memory allocator on Linux, you may experience memory fragmentation. To mitigate this, set the MALLOC_ARENA_MAX environment variable to 2 or 4 before starting the Node.js process.

    # Example: Set thread pool size to match CPU cores
    export UV_THREADPOOL_SIZE="$(lscpu -p | egrep -v "^#" | sort -u -t, -k 2,4 | wc -l)"
    
    # Example: Reduce memory fragmentation on glibc Linux
    export MALLOC_ARENA_MAX="2"
  3. Run the sharp performance benchmark

    main

    To run the official performance benchmarks comparing sharp against other libraries (like jimp, imagemagick, and gm), you must use Docker. The benchmark tests tasks such as JPEG decompression/resizing/compression and PNG processing.

    Follow these steps:

    1. Clone the repository.
    2. Navigate to the benchmark directory.
    3. Execute the Docker runner script.
    git clone https://github.com/lovell/sharp.git
    cd sharp/test/bench
    ./run-with-docker.sh
  4. Migrate from deprecated output format option functions to format-specific functions

    main

    In versions prior to v0.17.0, certain output format options were available as standalone functions. These have been deprecated in favor of passing options directly into the specific format function.

    Deprecated functions:

    • quality(n)
    • progressive(n)
    • compressionLevel(n)
    • withoutAdaptiveFiltering(n)
    • withoutChromaSubsampling(n)
    • trellisQuantisation(n) / trellisQuantization(n)
    • overshootDeringing(n)
    • optimiseScans(n) / optimizeScans(n)

    New Pattern: Instead of calling the option function directly, pass the option within the object argument of the format function (e.g., jpeg() or webp()).

    // Old way (deprecated in v0.17.0)
    sharp(input).quality(80).toFile('output.jpg');
    
    // New way
    sharp(input).jpeg({ quality: 80 }).toFile('output.jpg');
  5. Exclude sharp from bundlers

    main

    Because sharp uses native binaries, it must be excluded from your bundler's output.

    webpack

    Use the externals configuration:

    externals: {
      'sharp': 'commonjs sharp'
    }

    esbuild

    Use the --external flag or the external option in the API:

    esbuild app.js --bundle --platform=node --external:sharp

    For serverless-esbuild, configure packagerOptions in serverless.yml:

    custom:
      esbuild:
        external:
          - sharp
        packagerOptions:
          scripts:
            - npm install --os=linux --libc=glibc --cpu=x64 sharp

    vite

    Use build.rollupOptions.external:

    import { defineConfig } from 'vite';
    
    export default defineConfig({
      build: {
        rollupOptions: {
          external: ['sharp']
        }
      }
    });
  6. Install sharp via package managers

    main

    You can install sharp using any major JavaScript package manager. Ensure your package manager is configured to install optional dependencies, as this is how prebuilt binaries are fetched.

    npm install sharp
    pnpm add sharp
    yarn add sharp
    bun add sharp
    deno add --quiet npm:sharp
    npm install sharp
  7. Deploy sharp to AWS Lambda

    main

    The node_modules directory in your Lambda deployment package must include binaries for either linux-x64 or linux-arm64 depending on your chosen architecture.

    Recommendations:

    • If building on a different architecture, use the cross-platform installation methods described in the documentation.
    • Since AWS Lambda does not support symbolic links, consider using a third-party Lambda Layer (e.g., cbschuld/sharp-aws-lambda-layer or pH200/sharp-layer).
    • For best performance, select the largest available memory (a 1536 MB function provides ~12x more CPU time than a 128 MB function).
    • If using AWS API Gateway, ensure it is configured with relevant binary media types.