README.md
# aws-lambda-image
[![Build Status](https://travis-ci.org/ysugimoto/aws-lambda-image.svg?branch=master)](https://travis-ci.org/ysugimoto/aws-lambda-image)
[![Code Climate](https://codeclimate.com/github/ysugimoto/aws-lambda-image/badges/gpa.svg)](https://codeclimate.com/github/ysugimoto/aws-lambda-image)
[![Coverage Status](https://coveralls.io/repos/github/ysugimoto/aws-lambda-image/badge.svg?branch=master)](https://coveralls.io/github/ysugimoto/aws-lambda-image?branch=master)
[![npm version](https://badge.fury.io/js/aws-lambda-image.svg)](https://badge.fury.io/js/aws-lambda-image)
[![Join the chat at https://gitter.im/aws-lambda-image](https://img.shields.io/badge/GITTER-join%20chat-green.svg)](https://gitter.im/aws-lambda-image?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge&utm_content=badge)
An AWS Lambda Function to resize/reduce images automatically. When an image is
put on AWS S3 bucket, this package will resize/reduce it and put to S3.
## Requirements
- Node.js ( AWS Lambda supports versions of **8.10** or later )
### Important Notice
From `nodejs10.x`, AWS Lambda doesn't bundle `ImageMagick` and image related libraries.
https://forums.aws.amazon.com/thread.jspa?messageID=906619&tstart=0
Therefore, if you'd deploy with `nodejs10.x` runtime (but we prefer and default as it), it needs to install AWS Lambda Layer with this function.
This project can support it automatically, see [LAYERS](https://github.com/ysugimoto/aws-lambda-image/blob/master/doc/LAYERS.md) in detail.
## Preparation
Clone this repository and install dependencies:
```bash
git clone git@github.com:ysugimoto/aws-lambda-image.git
cd aws-lambda-image
npm install .
```
When upload to AWS Lambda, the project will bundle only needed files - no dev
dependencies will be included.
## Configuration
Configuration file you will find under the name `config.json` in project root.
It's copy of our example file `config.json.sample`. More or less it looks like:
```json
{
"bucket": "your-destination-bucket",
"backup": {
"directory": "./original"
},
"reduce": {
"directory": "./reduced",
"prefix": "reduced-",
"quality": 90,
"acl": "public-read",
"cacheControl": "public, max-age=31536000"
},
"resizes": [
{
"size": 300,
"directory": "./resized/small",
"prefix": "resized-",
"cacheControl": null
},
{
"size": 450,
"directory": "./resized/medium",
"suffix": "_medium"
},
{
"size": "600x600^",
"gravity": "Center",
"crop": "600x600",
"directory": "./resized/cropped-to-square"
},
{
"size": 600,
"directory": "./resized/600-jpeg",
"format": "jpg",
"background": "white"
},
{
"size": 900,
"directory": "./resized/large",
"quality": 90
}
]
}
```
### Configuration Parameters
| name | field | type | description |
|:-------------:|:-------------:|:-------:|--------------------------------------------------------------------------------------------------------------------------------------------------|
| bucket | - | String | Destination bucket name at S3 to put processed image. If not supplied, it will use same bucket of event source. |
| jpegOptimizer | - | String | Determine optimiser that should be used `mozjpeg` (default) or `jpegoptim` ( only `JPG` ). |
| acl | - | String | Permission of S3 object. [See AWS ACL documentation](http://docs.aws.amazon.com/AWSJavaScriptSDK/latest/AWS/S3.html#putObject-property). |
| cacheControl | - | String | Cache-Control of S3 object. If not specified, defaults to original image's Cache-Control. |
| keepExtension | - | Boolean | Global setting fo keeping original extension. If `true`, program keeps orignal file extension. otherwise use strict extension eg JPG,jpeg -> jpg |
| backup | - | Object | Backup original file setting. |
| | bucket | String | Destination bucket to override. If not supplied, it will use `bucket` setting. |
| | directory | String | Image directory path. Supports relative and absolute paths. Mode details in [DIRECTORY.md](doc/DIRECTORY.md/#directory) |
| | template | Object | Map representing pattern substitution pair. Mode details in [DIRECTORY.md](doc/DIRECTORY.md/#template) |
| | prefix | String | Prepend filename prefix if supplied. |
| | suffix | String | Append filename suffix if supplied. |
| | acl | String | Permission of S3 object. [See AWS ACL documentation](http://docs.aws.amazon.com/AWSJavaScriptSDK/latest/AWS/S3.html#putObject-property). |
| | cacheControl | String | Cache-Control of S3 object. If not specified, defaults to original image's Cache-Control. |
| | keepExtension | Boolean | If `true`, program keeps orignal file extension. otherwise, use strict extension eg JPG,jpeg -> jpg |
| | move | Boolean | If `true`, an original uploaded file will delete from Bucket after completion. |
| reduce | - | Object | Reduce setting following fields. |
| | quality | Number | Determine reduced image quality ( only `JPG` ). |
| | jpegOptimizer | String | Determine optimiser that should be used `mozjpeg` (default) or `jpegoptim` ( only `JPG` ). |
| | bucket | String | Destination bucket to override. If not supplied, it will use `bucket` setting. |
| | directory | String | Image directory path. Supports relative and absolute paths. Mode details in [DIRECTORY.md](doc/DIRECTORY.md/#directory) |
| | template | Object | Map representing pattern substitution pair. Mode details in [DIRECTORY.md](doc/DIRECTORY.md/#template) |
| | prefix | String | Prepend filename prefix if supplied. |
| | suffix | String | Append filename suffix if supplied. |
| | acl | String | Permission of S3 object. [See AWS ACL documentation](http://docs.aws.amazon.com/AWSJavaScriptSDK/latest/AWS/S3.html#putObject-property). |
| | cacheControl | String | Cache-Control of S3 object. If not specified, defaults to original image's Cache-Control. |
| | keepExtension | Boolean | If `true`, program keeps orignal file extension. otherwise, use strict extension eg JPG,jpeg -> jpg |
| resize | - | Array | Resize setting list of following fields. |
| | size | String | Image dimensions. [See ImageMagick geometry documentation](http://imagemagick.org/script/command-line-processing.php#geometry). |
| | format | String | Image format override. If not supplied, it will leave the image in original format. |
| | crop | String | Dimensions to crop the image. [See ImageMagick crop documentation](http://imagemagick.org/script/command-line-options.php#crop). |
| | gravity | String | Changes how `size` and `crop`. [See ImageMagick gravity documentation](http://imagemagick.org/script/command-line-options.php#gravity). |
| | quality | Number | Determine reduced image quality ( forces format `JPG` ). |
| | jpegOptimizer | String | Determine optimiser that should be used `mozjpeg` (default) or `jpegoptim` ( only `JPG` ). |
| | orientation | Boolean | Auto orientation if value is `true`. |
| | bucket | String | Destination bucket to override. If not supplied, it will use `bucket` setting. |
| | directory | String | Image directory path. Supports relative and absolute paths. Mode details in [DIRECTORY.md](doc/DIRECTORY.md/#directory) |
| | template | Object | Map representing pattern substitution pair. Mode details in [DIRECTORY.md](doc/DIRECTORY.md/#template) |
| | prefix | String | Prepend filename prefix if supplied. |
| | suffix | String | Append filename suffix if supplied. |
| | acl | String | Permission of S3 object. [See AWS ACL documentation](http://docs.aws.amazon.com/AWSJavaScriptSDK/latest/AWS/S3.html#putObject-property). |
| | cacheControl | String | Cache-Control of S3 object. If not specified, defaults to original image's Cache-Control. |
| | keepExtension | Boolean | If `true`, program keeps orignal file extension. otherwise, use strict extension eg JPG,jpeg -> jpg |
| optimizers | - | Object | Definitions for override the each Optimizers command arguments. |
| | pngquant | Array | `Pngquant` command arguments. Default is `["--speed=1", "256"]`. |
| | jpegoptim | Array | `Jpegoptim` command arguments. Default is `["-s", "--all-progressive"]`. |
| | mozjpeg | Array | `Mozjpeg` command arguments. Default is `["-optimize", "-progressive"]`. |
| | gifsicle | Array | `Gifsicle` command arguments. Default is `["--optimize"]`. |
Note that the `optmizers` option will **force** override its command arguments, so if you define these configurations, we don't care any more about how optimizer works.
### Testing Configuration
If you want to check how your configuration will work, you can use:
```bash
npm run test-config
```
## Installation
### Setup
To use the automated deployment scripts you will need to have
[aws-cli installed and configured](http://docs.aws.amazon.com/cli/latest/userguide/installing.html).
Deployment scripts are pre-configured to use some default values for the Lambda
configuration. I you want to change any of those just use:
```bash
npm config set aws-lambda-image:profile default
npm config set aws-lambda-image:region eu-west-1
npm config set aws-lambda-image:memory 1280
npm config set aws-lambda-image:timeout 5
npm config set aws-lambda-image:name lambda-function-name
npm config set aws-lambda-image:role lambda-execution-role
```
Note that `aws-lambda-image:name` and `aws-lambda-image:role` are optional.
If you want to change lambda function name or execution role, type above commands before deploy.
And make sure AWS Lambda Layer has installed in your account/region.
See [LAYERS](https://github.com/ysugimoto/aws-lambda-image/blob/master/doc/LAYERS.md) for instructions.
### Deployment
Command below will deploy the Lambda function on AWS, together with setting up
roles and policies.
```bash
npm run deploy
```
*Notice*: Because there are some limitations in `Claudia.js` support for
policies, which could lead to issues with `Access Denied` when processing
images from one bucket and saving them to another, we have decided to introduce
support for custom policies.
#### Custom policies
Policies which should be installed together with our Lambda function are stored
in `policies/` directory. We keep there policy that grants access to all
buckets, which is preventing possible errors with `Access Denied` described
above. If you have any security-related concerns, feel free to change the:
```json
"Resource": [
"*"
]
```
in the `policies/s3-bucket-full-access.json` to something more restrictive,
like:
```json
"Resource": [
"arn:aws:s3:::destination-bucket-name/*"
]
```
Just keep in mind, that you need to make those changes before you do the
deployment.
### Adding S3 event handlers
To complete installation process you will need to take one more action. It will
allow you to install S3 Bucket event handler, which will send information about
all uploaded images directly to your Lambda function.
```bash
npm run add-s3-handler --s3_bucket="your-bucket-name" --s3_prefix="directory/" --s3_suffix=".jpg"
```
You are able to install multiple handlers per Bucket. So, to add handler for PNG
files you just need to re-run above command with different _suffix_, ie:
```bash
npm run add-s3-handler --s3_bucket="your-bucket-name" --s3_prefix="directory/" --s3_suffix=".png"
```
### Adding SNS message handlers
As an addition, you can also setup and SNS message handler in case you would
like to process S3 events over an SNS topic.
```bash
npm run add-sns-handler --sns_topic="arn:of:SNS:topic"
```
### Updating
To update Lambda with you latest code just use command below. Script will build
new package and automatically publish it on AWS.
```bash
npm run update
```
### More
For more scripts look into [package.json](package.json).
## Complete / Failed hooks
You can handle resize/reduce/backup process on success/error result on
`index.js`. `ImageProcessor::run` will return `Promise` object, run your
original code:
```javascript
processor.run(config)
.then(function(proceedImages)) {
// Success case:
// proceedImages is list of ImageData instance on you configuration
/* your code here */
// notify lambda
context.succeed("OK, numbers of " + proceedImages.length + " images has proceeded.");
})
.catch(function(messages) {
// Failed case:
// messages is list of string on error messages
/* your code here */
// notify lambda
context.fail("Woops, image process failed: " + messages);
});
```
## Image resize
- `ImageMagick` (installed on AWS Lambda)
## Image reduce
- [cjpeg](https://github.com/mozilla/mozjpeg)
- [jpegoptim](https://github.com/tjko/jpegoptim)
- [pngquant](https://pngquant.org/)
- [gifsicle](https://github.com/kohler/gifsicle)
## License
MIT License.
## Author
Yoshiaki Sugimoto
## Image credits
Thanks for testing fixture images:
- [pngimg](http://pngimg.com/)
- [pakutaso](https://www.pakutaso.com/)