easy-gd Build Status
A simplified Node.js wrapper around GD image manipulation library with extra features:
- Image format autodetection: just
gd.open(file)instead of choosing between gd.createFromJpeg() or gd.createFromPng() or whatever. - Handy resizing and watermarking shortcuts:
image.resize({width: 100, height:100})andimage.watermark('logo.png'). - Reads/writes files, buffers and streams.
- Provides synchronous, asynchronous and transform stream interfaces.
- Has built-in Exif parsing and supports automatic image orientation.
- A drop-in replacement for node-gd. You can just
require('easy-gd')instead ofrequire('node-gd')and everything will be working as before.
Because it is fast. Easy-gd uses C++ buindings for libgd that add very little overhead. For example, it resizes images two times faster than gm, which executes graphicsmagick commands in the background.
Node.js 0.8-0.10.
Ubuntu:
sudo apt-get install libgd2-xpm-dev npm install easy-gd
Mac OS X:
brew install gd npm install easy-gd
- Resizing images
- Placing a watermark
- Reading/writing image files
- Reading/writing buffers
- Reading/writing streams
- Image transform streams
- Synchronous image processing
- Asynchronous image processing
- Controlling the output format
- Controlling image quality/compression
- Automatic filename extensions
- Reading Exif data
- Automatic image orientation
- Error handling
var gd = require('easy-gd') var image, resized image = gd.open('image-800x600.jpg') // Source image size is ×ばつ600 // Resize to feat into ×ばつ100 box, yields ×ばつ75 image resized = image.resize({width: 100, height: 100}) // Resize by width, yields ×ばつ150 image resized = image.resize({width: 200}) // Resize by height, yields ×ばつ200 image resized = image.resize({height: 200}) // Resize and crop to ×ばつ100 resized = image.crop({width: 100, height: 100}) resized = image.resize({width: 100, height: 100, method: 'crop'}) // Resize without resampling; faster but lowers the quality resized = image.resize({width: 100, height: 100, resample: false}) // Save the resized image resized.save('resized.jpg')
See also: Reading/writing files, Asynchronous processing, Image transform streams.
var gd = require('easy-gd') var image, watermarked image = gd.open('source-image.jpg') // Place a logo at the center of the image watermarked = image.watermark('logo.png') watermarked = image.watermark('logo.png', {x: 0.5, y: 0.5}) // At the left top corner watermarked = image.watermark('logo.png', {x: 0, y: 0}) // At the right bottom corner watermarked = image.watermark('logo.png', {x: 1, y: 1}) // Choose the most contrast position for a logo at the bottom watermarked = image.watermark('logo.png', [{x: 0, y: 1}, {x: 0.5, y: 1}, {x: 1, y: 1}]) // Using gd.Image object as a watermark var logo = gd.open('logo.png') watermarked = image.watermark(logo) // Save the watermarked image watermarked.save('watermarked.jpg')
See also: Reading/writing files, Reading/writing buffers, Reading/writing streams, Asynchronous processing, Error handling.
var gd = require('easy-gd') var image = gd.open('image.png') // Do something to the image image.save('processed.jpg', {quality: 90})
See also: Reading/writing buffers, Reading/writing streams, Asynchronous processing, Controlling the output format, Error handling.
var gd = require('easy-gd') // Reading image from buffer var image = gd.open(imageData) // Saving image to a buffer var imageData = image.save() // Using buffer as a watermark source var watermarked = image.watermark(imageData)
See also: Reading/writing files, Reading/writing streams, Asynchronous processing, Controlling the output format, Error handling.
var gd = require('easy-gd') // Reading image from stream gd.open(stream, function (error, image) { if (!error) { // Process the image } }) // Saving image to a stream image.save(stream, function (error) { if (!error) { // Some action } }) // Using stream as a watermark source image.watermark(stream, function (error, watermarked) { if (!error) { // Process the watermarked image } })
See also: Image transform streams, Reading/writing files, Reading/writing buffers, Controlling the output format, Error handling.
All the image manipulation methods called directly on the module object produce chainable transform streams:
var gd = require('easy-gd') // Making thumbnails process.stdin .pipe(gd.crop({width: 100, height: 100})) .pipe(process.stdout) // Watermarking process.stdin .pipe(gd.watermark('logo.png')) .pipe(process.stdout) // Changing image format process.stdin .pipe(gd.format('jpeg').quality(90)) .pipe(process.stdout) // Combine everything process.stdin .pipe( gd.resize({width: 800, height: 600}) .watermark('logo.png', {x:1, y:1}) .options({format: 'jpeg', quality: '90'}) ) .pipe(process.stdout)
See also: Reading/writing files, Reading/writing buffers, Reading/writing streams, Controlling the output format, Error handling.
With easy-gd you can synchronously process files and buffers:
var gd = require('easy-gd') // Processing files gd.open('input.png') .resize({width: 800, height: 600}) .save('output.jpg', {quality: 90}) // Processing buffers var outputData = gd.open(inputData) .resize({width: 800, height: 600}) .save({format: 'jpeg', quality: 90})
See also: Asynchronous processing, Error handling.
You can asynchronously process files, buffers and streams by passing additional callback argument:
var gd = require('easy-gd') // Processing files gd.open('input.png', function (error, image) { if (error) throw error image.resize({width: 800, height: 600}, function (error, resized) { if (error) throw error resized.save('output.jpg', {quality: 90}, function (error) { if (error) throw error }) }) }) // Processing buffers gd.open(inputData, function (error, image) { if (error) throw error image.resize({width: 800, height: 600}, function (error, resized) { if (error) throw error resized.save({format: 'jpeg', quality: 90}, function (error, outputData) { if (error) throw error // Process outputData buffer }) }) }) // Processing streams gd.open(inputStream, function (error, image) { if (error) throw error image.resize({width: 800, height: 600}, function (error, resized) { if (error) throw error resized.save(outputStream, {format: 'jpeg', quality: 90}, function (error) { if (error) throw error }) }) })
See also: Image transform streams, Synchronous processing, Error handling.
var gd = require('easy-gd') // Format is inherited from the source image var image = gd.open('input.jpg') var resizedBuffer = image.resize({width: 100}).save() // Saved in JPEG // Format can be specified explicitly with target filename extension var image = gd.open('input.jpg') image.save('output.png') // Saved in PNG // Format can be specified explicitly with save({format: 'format_name'}) var image = gd.open('input.jpg') var pngBuffer = image.save({format: 'png'}) // Saved in PNG // Target file extension has higher priority var image = gd.open('input.png') image.save('output.jpg') // Saved in JPEG
Format specification priority: filename extension > save 'format' option > inherited format.
See also: Controlling image quality/compression, Automatic filename extensions, Error handling.
var gd = require('easy-gd') var image = gd.open('input.jpg') // Setting JPEG file quality, 0-100 image.save('output.jpg', {quality: 90}) // Setting PNG file compression level, 0-9 image.save('ouput.png', {compression: 6}) // Transform stream options inputStream.pipe(gd.format('png').compression(6)).pipe(outputStream) inputStream.pipe(gd.format('jpeg').quality(90)).pipe(outputStream) inputStream.pipe(gd.options({format: 'jpeg', quality: 90}).pipe(outputStream) // Buffer saving options var outputBuffer = image.save({format: 'jpeg', quality: 90}) var outputBuffer = image.save({format: 'png', compression: 6})
See also: Controlling the output format, Automatic filename extensions.
var gd = require('easy-gd') var image = gd.open('input.jpg') image.save('output.{ext}', {format: 'png'}) // Writes ouput.png var image = gd.open('input.jpg') image .resize({width: 100}) .save('output.{ext}') // Writes output.jpg since format was inherited
See also: Controlling the output format, Controlling image quality/compression.
Exif data are being parsed automatically for JPEG images.
var gd = require('easy-gd') var image = gd.open('input.jpg') // Accessing Exif tags if (image.exif) { console.log('%s %s', image.exif.GPSLongitude, image.exif.GPSLatitude) } else { console.log('No Exif data') }
Note: image.exif property will be copied by resize() and other methods, but will not be written to the destination image.
See also: Automatic image orientation.
GD does not process Exif data, resulting rotated images in the output. Easy-gd fixes this by automatically orienting the image.
var gd = require('easy-gd') // The image gets automatically oriented by Exif data var image = gd.open('photo.jpg') // Turn automatic orientation off var original = gd.open('photo.jpg', {autoOrient: false}) // Automatically orient existing image var rotated = original.autoOrient()
See also: Reading Exif data.
var gd = require('easy-gd') // Synchronous methods throw exceptions try { var image = gd.open('non-existent.png') } catch (error) { console.log('Failed to open the image: %s', error) } // Asynchronous methods return errors as the first callback argument; // null means there was no error gd.open('non-existent.png', function (error, image) { if (error) { console.log('Failed to open the image: %s', error) return } // ... }) // Every error raised or returned by easy-gd is a descendant or gd.Error try { doImageRelatedStuff() } catch (error) { if (error instanceof gd.Error) { console.log('Image processing error: %s', error) } else { // Some other error happened } }
There are some subclasses you can use to catch specific errors:
- gd.UnknownSourceType - unknown source type.
- gd.EmptySource - empty source file or buffer.
- gd.UnknownImageFormat - unknown image format (or not an image at all).
- gd.IncompleteImage - corrupted or incomplete image.
- gd.UnsupportedOrientation - unsupported image Exif orientation tag value.
- gd.DestinationFormatRequired - destination image format required.
- gd.UnknownDestinationType - unknown destination type.
- gd.FileOpen - file opening error.
- gd.FileDoesNotExist - file does not exist.
- gd.FileWrite - file writing error.
- gd.SynchronousStreamAccess - a stream cannot be read or written synchronously.
- gd.OptionsRequired - options argument should be passed in.