@sapphirejs/image

0.0.13 • Public • Published

Image

An intuitive image manipulation package using the blazing fast sharp, so all credits go to that library. All it does is a tiny bit of abstraction, just enough to better integrate it in the framework and [probably] make it easier to use. The rest are direct calls to sharp's functions.

Usage

Before installing the library, just be aware that it includes libvips, a 7MB download that serves as sharp's image manipulation engine.

$ npm install --save @sapphirejs/image

We'll resize an image, rotate it, apply a grayscale effect, and finally save it somewhere in disk:

const Image = require('@sapphirejs/image')

const image = new Image()
await image.open('path/to/image.jpg', image => {
  image
    .resize(600, 400)
    .rotate(90)
    .grayscale()
    .jpeg('smaller.jpg')
})

The fluent interface allows for some very readable actions, but also serves a purpose: encapsulating the image call into a callback that actually returns a Promise. Notice the await keyword in front of image.open(). You may have also noticed that it isn't called in an async function, but we've omitted it for brevity's sake.

Only the functions that actually persist a file to disk will return a Promise: jpeg(), png(), webp() and save(). Without one of them at the end of the chain, the library won't complain, but nothing helpful will happen.

In the same way as the previous example, instead of opening an existing image, you can also create a brand new one. The following creates a 100x100px image with a semi-transparent red background.

await image.create({
  with: 100,
  height: 100,
  channels: 4,
  background: { r: 255, g: 0, b: 0, alpha: 128 }
}, image => {
  image
    .png('red.png')
})

Accessing the Sharp Instance

We've created this package with the hopes that it will serve most people's image manipulation needs while building web applications. However, there may be something we haven't abstracted from sharp, so you may need to access the instance directly.

The open(path) is equivalent to calling sharp(path). Instead of a string pointing to a system file, it can be also a Buffer.

In the callback, you can access the sharp instance with the raw property:

await image.open('path/to/image.jpg', (image) => {
  image
    .raw
    .trim()
    .normalize()
    .jpeg()
    .toFile('export.jpg')
})

Image Composers

We're calling them arbitrarily image composers, but they're nothing but a pattern to reuse functions for typical image operations. Let's say you resize images to fixed dimensions as thumbnails, and you do that in a few parts of your application. Writing the same code over and over wouldn't be that practical, so you need some way to reuse it. While there are plenty of ways, we've been using the following approach:

// helper file
const resizeThumbnail = (output) => {
  return image => {
    image
      .resize(100, 100)
      .enhance()
      .sharpen()
      .jpeg(output)
  }
}

That reusable function that itself returns a function, you can reuse anywhere you need to resize an image to 100x100px and also do some contrast enhancing, and sharpening. Now it's as simple as passing it to image.open():

await image.open('path/to/image.jpg', resizeThumbnail('output.jpg'))

Such an approach keeps it simple by not abstracting away the library, but also allows plenty of flexibility. Obviously, this will bring you that far, as for bigger or complex applications you may need higher abstractions.

API

resize(width, height) Resize the image to a new width and height by disallowing enlargement. If one of the parameters is null or undefined, it will be calculated automatically by keeping the aspect ratio.

widen(width) Same as resize(width).

heighten(height) Same as resize(null, height).

crop(gravity) Crop the image to the dimensions set in resize(). The gravity may be a Image.gravity or Image.strategy constant. Defaults to Image.gravity.center. Check out sharp's docs for a list of gravities and strategies.

ignoreRatio() Ignore aspect ratio on resize.

enlarge() Allow enlargement when the resizing dimensions are bigger than the original image's with or height.

rotate(angle) Rotate the image to a specific angle. If not set, infer the appropriate rotation based on EXIF data, if any. When set, it must be a multiple of 90.

flip(axis) Flip the image on axis. Axis can be either Image.axis.y or Image.axis.x, set by default to the y axis.

sharpen() Sharpen the image with a mild, but fast algorithm.

blur(amount) Blur the image with amount. When the amount is not set, perform a mild, but fast blurring. Otherwise, it expects an amount that ranges from 0 to 100. That is in contrast to the underlying sharp that expects a value between 0.3 and 1000, as a sigma of the Gaussian mask.

extend(extend) Extend the image outside its canvas, as a sort of padding. It expects an object that contains the top, bottom, left and right values: { top: 10, bottom: 5, left: 0, right: 25 }.

flatten() Merge the alpha transparency channel with the provided background, if any. image.background({ r: 255, g: 0, b: 0, alpha: 255 }).flatten()

gamma(value) Apply gamma correction to the image. Value ranges between 1.0 and 3.0.

negative() Convert the image to its negative.

enhance() Applies contrast enhancement.

background(color) Set a background color the image. Especially useful if combined with flatten() or extend(). image.background({ r: 255, g: 0, b: 0, alpha: 255 })

grayscale() Convert the image to 8-bit, 256 colors grayscale.

overlay(path, options) Add an image as an overlay to the existing one. Especially useful for watermarks. Expects a path to the image and an object as options: { gravity: Image.gravity.southeast, top: 5, left: 10, tile: false }

metadata() Returns information about the image.

jpeg(path, options) Save the processed image to path as JPEG. Default options: { quality: 90, progressive: true }.

png(path, options) Save the processed image to path as PNG. Default options: { progressive: true }.

webp(path, options) Save the processed image to path as WebP. Default options: { progressive: true }.

save(path) Save the processed image to path by inferring the format from the file extension. With the format-specific methods above, there's little reason to use this function.

Package Sidebar

Install

npm i @sapphirejs/image

Weekly Downloads

0

Version

0.0.13

License

MIT

Unpacked Size

15.4 kB

Total Files

6

Last publish

Collaborators

  • aleksanderkoko
  • fadion