GithubHelp home page GithubHelp logo

furagu / easy-gd Goto Github PK

View Code? Open in Web Editor NEW
25.0 5.0 14.0 1.54 MB

A simplified Node.js wrapper around GD image manipulation library with extra features making your life easier.

License: MIT License

JavaScript 99.62% Makefile 0.38%

easy-gd's Introduction

easy-gd Build Status

A simplified Node.js wrapper around GD image manipulation library with extra features:

Why should one use easy-gd?

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.

Compatibility

Node.js 0.8-0.10.

Installation

Ubuntu:

sudo apt-get install libgd2-xpm-dev
npm install easy-gd

Mac OS X:

brew install gd
npm install easy-gd

Usage recipes

Resizing images

var gd = require('easy-gd')

var image, resized

image = gd.open('image-800x600.jpg') // Source image size is 800×600

// Resize to feat into 100×100 box, yields 100×75 image
resized = image.resize({width: 100, height: 100})

// Resize by width, yields 200×150 image
resized = image.resize({width: 200})

// Resize by height, yields 267×200 image
resized = image.resize({height: 200})

// Resize and crop to 100×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.

Placing a watermark

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.

Reading/writing image files

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.

Reading/writing buffers

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.

Reading/writing streams

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.

Image transform streams

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.

Synchronous image processing

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.

Asynchronous image processing

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.

Controlling the output format

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.

Controlling image quality/compression

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.

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.

Reading Exif data

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.

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.

Error handling

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.

easy-gd's People

Contributors

furagu avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar

easy-gd's Issues

gd.createFromPtr() fires callback multiple times

Looks like gd.createFromPtr() fires callback multiple times in some conditions:

/usr/home/rei/node_modules/async/lib/async.js:22
            if (called) throw new Error("Callback was already called.");
                              ^
Error: Callback was already called.
    at /usr/home/rei/node_modules/async/lib/async.js:22:31
    at /usr/home/rei/node_modules/async/lib/async.js:226:17
    at /usr/home/rei/index.js:98:13
    at /usr/home/rei/node_modules/easy-gd/index.js:53:25
    at /usr/home/rei/node_modules/easy-gd/node_modules/exif/lib/exif/ExifImage.js:46:5
    at ExifImage.processImage (/usr/home/rei/node_modules/easy-gd/node_modules/exif/lib/exif/ExifImage.js:116:2)
    at ExifImage.loadImage (/usr/home/rei/node_modules/easy-gd/node_modules/exif/lib/exif/ExifImage.js:62:8)
    at new ExifImage (/usr/home/rei/node_modules/easy-gd/node_modules/exif/lib/exif/ExifImage.js:44:8)
    at Object.gd.createFromPtr (/usr/home/rei/node_modules/easy-gd/index.js:52:27)
    at /usr/home/rei/index.js:90:12

installation error

npm i easy-gd

gyp ERR! configure error
gyp ERR! stack Error: Can't find Python executable "python", you can set the PYT
HON env variable.
gyp ERR! stack at PythonFinder.failNoPython (C:\Users\eldeeb\AppData\Roaming
\npm\node_modules\npm\node_modules\node-gyp\lib\configure.js:484:19)
gyp ERR! stack at PythonFinder. (C:\Users\eldeeb\AppData\Roaming
npm\node_modules\npm\node_modules\node-gyp\lib\configure.js:509:16)
gyp ERR! stack at C:\Users\eldeeb\AppData\Roaming\npm\node_modules\npm\node_
modules\graceful-fs\polyfills.js:282:31
gyp ERR! stack at FSReqWrap.oncomplete (fs.js:154:21)
gyp ERR! System Windows_NT 6.3.9431
gyp ERR! command "C:\Program Files\nodejs\node.exe" "C:\Users\eldeeb\AppDa
ta\Roaming\npm\node_modules\npm\node_modules\node-gyp\bin\node-gyp.js" "
rebuild"
gyp ERR! cwd D:\Downloads__projects\NodeJs\Tests\test-packages\node_modules\buf
fertools
gyp ERR! node -v v10.14.1
gyp ERR! node-gyp -v v3.8.0
gyp ERR! not ok
npm WARN [email protected] No repository field.

npm ERR! code ELIFECYCLE
npm ERR! errno 1
npm ERR! [email protected] install: node-gyp rebuild
npm ERR! Exit status 1
npm ERR!
npm ERR! Failed at the [email protected] install script.
npm ERR! This is probably not a problem with npm. There is likely additional log
ging output above.

Alpha channel turns black

Thanks for this library, it's great!

One problem I've found when adding watermarks to PNGs with transparency is that the transparency turns black.

Any ideas on how to fix this?

Dependencies out of date

node-gd needs updating to the latest version to avoid node-gyp breaking on latest versions of OS X

Read image dimension

Hi

I need to read image dimension for validity. How can I access to image dimension ?

I can't access them using exif, so how can I do this?

Animated GIFs

Quick question. Can your library handle animated GIFs?

A quick test shows that watermarking an animated GIF results in a static GIF containing the first frame with the watermark successfully applied. Is this expected behaviour?

I imagine that in order to watermark an animated GIF that I would need to detect that it is animated, break the animation up into separate images, watermark each one and then reassemble them. Can I do that with easy-gd or do I need to find another library to do the detection, separation and assembling?

npm install fails for me on OS X Yosemite

On OS X Yosemite, node v4.3.1, npm 2.14.12, running npm install easy-gd fails when compiling node-gd.cpp:

CXX(target) Release/obj.target/node_gd/cpp/node-gd.o
../cpp/node-gd.cpp:17:10: fatal error: 'gd.h' file not found

include <gd.h>

     ^

1 error generated.

I have done the "brew install gd" step. I see gd.h in /usr/local/include. Running npm install node-gd successfully installs node-gd 1.1.0.

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.