AWS Lambda Layer providing sharp with HEIC (and WebP) support
- Docker
- A recent AWS SAM CLI release with
nodejs24.xsupport - Node v24 (for v6.x)
Due to potential license concerns for the HEVC patent group, this repo can't be provided in the most convenient way which would be a shared lambda layer or an Application in the AWS Serverless Repo.
But you can compile and deploy this lambda layer yourself at your own risk and use it wihin your own accounts. All you need is an S3 bucket to deploy the compiled code to (replace your-s3-bucket in the code snippet below). Please see the note below regarding the build process.
It is recommended to automate this process using AWS CodeBuild. A buildspec file is provided in the repo. In that case you'll have to set the SAM_BUCKET environment variable in CodeBuild. For other environment variables see the table below. Use an Amazon Linux 2023 standard image such as aws/codebuild/amazonlinux-x86_64-standard:6.0.
A sample CloudFormation template is provided to setup the CodeBuild project, sample-buildproject.yaml.
npm run build
SAM_BUCKET=your-s3-bucket npm run deployThe example can be deployed using the following commands
cd examples
sam build
sam deploy --guided- Add the lambda layer with ARN
arn:aws:lambda:us-east-1:${AWS:AccountId}:layer:sharp-heic:${LAYER_VERSION}to any lambda function (replace${LAYER_VERSION}with the appropriate version and${AWS:AccountId}if you're not using a layer from the same account as the function). You can also import the layer ARN using!ImportValue SharpHEICLayerArn. - Remove sharp from the dependencies in the function code (it will otherwise conflict with the one provided through the layer)
- When encoding HEIC (
heif({ compression: 'hevc' })), passtune: 'ssim'ortune: 'psnr'. sharp's defaulttune: 'auto'is rejected by the x265 encoder withheif: Invalid parameter value (5.2006), see lovell/sharp#4621. AVIF (compression: 'av1') is not affected. - See example template for a complete sample template.
| Name | Required | Default Value | Description |
|---|---|---|---|
| SAM_BUCKET | yes | Name of S3 Bucket to store layer | |
| S3_PREFIX | no | sharp-heic-lambda-layer | Prefix within S3 Bucket to store layer |
| STACK_NAME | no | sharp-heic-lambda-layer | Name of CloudFormation stack |
| LAYER_NAME | no | sharp-heic | Name of layer |
| AWS_REGION | no | us-east-1 | AWS Region to deploy to |
| ORGANIZATION_ID | no | none | ID of Organization to grant access to layer |
| PRINCIPAL | no | account | Principal to grant access to layer |
For details on ORGANIZATION_ID and PRINCIPAL please see the equivalent properties in the CloudFormation Docs.
The special value none for ORGANIZATION_ID is used to disable organization based access.
The special value account for PRINCIPAL is used to give access to the account the layer is deployed to.
The environment variables are used to create a samconfig.toml file that configures the sam package and sam deploy commands.
Previously, some custom docker images were needed to build this layer. AWS now publishes managed SAM build images for current Lambda runtimes, including public.ecr.aws/sam/build-nodejs24.x.
The Test layer workflow builds the layer with sam build --use-container and mounts the result at /opt in the public.ecr.aws/lambda/nodejs:24 runtime image. There it runs test/layer.test.js, which checks shared library resolution, the libvips and sharp versions, HEIC decoding, WebP resizing, HEIF encoding with both HEVC and AV1, static and animated GIF output, and palette PNG output. Pixel colours are verified against test/fixtures/quadrants.heic, a synthetic image encoded with macOS sips (regenerate with node test/fixtures/make-quadrants-heic.js). The layer is only rebuilt when layer/, test/, examples/src/, template.yaml or the workflow itself change; for other changes (e.g. documentation) the build job is skipped. It also invokes the example function through the Lambda Runtime Interface Emulator.
This repo exists as it is rather painful to compile all libraries required to get sharp to work with HEIC/HEIF files in an AWS Lambda environment. The sharp repository has several issues related to this.
This lambda layer contains the node module sharp. But unlike a normal installation via npm i sharp this layer does not use the prebuilt sharp and libvips binaries. This layer compiles libwebp, libde265, x265, libaom, libheif, libimagequant, cgif, and libvips from source, then explicitly runs sharp's build script against that global libvips installation in order to provide HEIC/HEIF (and WebP) functionality in an AWS Lambda environment.
As of sharp@0.35.1, building from source is no longer triggered automatically during npm install, so the layer build now installs the package first and then runs sharp's build script against the custom libvips installation.
The native build is intentionally pinned end-to-end so the layer uses the versions listed below instead of whatever happens to be available in the build image.
The following table lists the release version of this repo together with the version of each dependency. Patch versions are related to the build process or documentation and have the same dependencies as the minor version.
| release | sharp | libvips | libheif | libwebp | libde265 | x265 | libaom | libimagequant | cgif | nodejs |
|---|---|---|---|---|---|---|---|---|---|---|
| 1.2.0 | 0.28.2 | 8.10.6 | 1.12.0 | 1.2.0 | 1.0.8 | - | - | - | 12 | |
| 1.1.0 | 0.27.0 | 8.10.5 | 1.10.0 | 1.1.0 | 1.0.8 | - | - | - | 12 | |
| 2.0.0 | 0.29.1 | 8.11.3 | 1.12.0 | 1.2.1 | 1.0.8 | - | - | - | 14 | |
| 3.0.0 | 0.30.7 | 8.12.2 | 1.12.0 | 1.2.4 | 1.0.8 | - | - | - | 16 | |
| 3.1.0 | 0.30.7 | 8.12.2 | 1.12.0 | 1.2.4 | 1.0.8 | - | - | - | 16 | |
| 3.2.0 | 0.30.7 | 8.12.2 | 1.12.0 | 1.3.2 | 1.0.12 | - | - | - | 16 | |
| 4.1.0 | 0.33.3 | 8.15.2 | 1.17.6 | 1.4.0 | 1.0.15 | 3.6 | - | - | 20 | |
| 4.1.3 | 0.33.3 | 8.15.2 | 1.17.6 | 1.4.0 | 1.0.15 | 3.6 | - | - | 20 | |
| 4.2.0 | 0.33.5 | 8.15.3 | 1.18.2 | 1.4.0 | 1.0.15 | 3.6 | 3.9.1 | - | - | 20 |
| 5.0.0 | 0.34.3 | 8.17.1 | 1.20.1 | 1.6.0 | 1.0.16 | 4.1 | 3.12.1 | - | - | 22 |
| 5.1.0 | 0.34.4 | 8.17.2 | 1.20.2 | 1.6.0 | 1.0.16 | 4.1 | 3.13.1 | - | - | 22 |
| 6.0.0 | 0.34.5 | 8.17.3 | 1.21.2 | 1.6.0 | 1.0.16 | 4.1 | 3.13.1 | - | - | 24 |
| 6.1.0 | 0.35.1 | 8.18.3 | 1.23.0 | 1.6.0 | 1.0.18 | 4.1 | 3.14.1 | - | - | 24 |
| 6.2.0 | 0.35.5 | 8.18.7 | 1.23.6 | 1.6.0 | 1.1.3 | 4.2 | 3.15.1 | - | - | 24 |
| 6.3.0 | 0.35.5 | 8.18.7 | 1.23.6 | 1.6.0 | 1.1.3 | 4.2 | 3.15.1 | 2.4.1 | 0.5.4 | 24 |
libvips needs cgif to write GIF files and an image quantiser to write GIF and palette PNG (png({ palette: true })) files. The layer builds cgif 0.5.4 and the BSD-licensed libimagequant 2.4.1 fork also used by sharp's prebuilt binaries. Without them, saving a GIF fails with VipsOperation: class "gifsave_buffer" not found (#13), and palette: true is ignored.
libvips 8.18.3 and earlier cap libheif's max_items at 16 when loading HEIF/HEIC files. Many files written by recent phone cameras exceed this (for example iinf, iref and ipma boxes with 20 to 50 entries) and fail to load with Security limit exceeded. libvips 8.18.4 raised these limits, and sharp 0.35.5 requires libvips 8.18.7 or later, so the layer no longer needs any patching to load these files.
nodejs12.x(v1.x)nodejs14.x(v2.x)nodejs16.x(v3.x)nodejs20.x(v4.x)nodejs22.x(v5.x)nodejs24.x(v6.x)
If you would like to contribute to this repository, please open an issue or submit a PR.
You can also use the Sponsor button on the right if you'd like.
- libheif and libde265 are distributed under the terms of the GNU Lesser General Public License. Copyright Struktur AG. See https://github.com/strukturag/libheif/blob/master/COPYING and https://github.com/strukturag/libde265/blob/master/COPYING for details.
- x265 is free to use under the GNU GPL and is also available under a commercial license. See https://www.x265.org/ for details.
- libwebp is Copyright Google Inc. See https://github.com/webmproject/libwebp/blob/master/COPYING for details.
- sharp is licensed under the Apache License, Version 2.0. Copyright Lovell Fuller and contributors. See https://github.com/lovell/sharp/blob/master/LICENSE for details.
- libvips is licensed under the LGPL 2.1+. See https://github.com/libvips/libvips/blob/master/COPYING for details.
- cgif is licensed under the MIT License. Copyright Daniel Löbl. See https://github.com/dloebl/cgif/blob/main/LICENSE for details.
- libimagequant 2.4.x is licensed under the BSD 2-Clause License. Copyright Greg Roelofs and Kornel Lesiński. See https://github.com/lovell/libimagequant/blob/main/COPYRIGHT for details.
- libaom is subject to the terms of the BSD 2 Clause License and the Alliance for Open Media Patent License 1.0. See https://aomedia.googlesource.com/aom/#license-header
- The remainder of the code in this repository is licensed under the MIT License. See LICENSE for details.
Visit sharp.pixelplumbing.com for complete instructions on sharp.