npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2024 – Pkg Stats / Ryan Hefner

@sapphirejs/image

v0.0.13

Published

Image Processing and Manipulation Sapphire Framework

Downloads

3

Readme

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.