Huge News!Announcing our $40M Series B led by Abstract Ventures.Learn More
Socket
Socket
Sign inDemoInstall

sharp

Package Overview
Dependencies
Maintainers
1
Versions
156
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

sharp - npm Package Compare versions

Comparing version 0.13.1 to 0.14.0

2

CONTRIBUTING.md

@@ -44,5 +44,5 @@ # Contributing to sharp

| ------: | :--------- |
| v0.14.0 | needle |
| v0.15.0 | outfit |
| v0.16.0 | pencil |
| v0.17.0 | quill |

@@ -49,0 +49,0 @@ Please squash your changes into a single commit using a command like `git rebase -i upstream/<wip-branch>`.

@@ -30,2 +30,3 @@ # API

JPEG, PNG or WebP format image data can be streamed out from this object.
When using Stream based output, derived attributes are available from the `info` event.

@@ -41,2 +42,15 @@ ```javascript

```javascript
// Read image data from readableStream,
// resize to 300 pixels wide,
// emit an 'info' event with calculated dimensions
// and finally write image data to writableStream
var transformer = sharp()
.resize(300)
.on('info', function(info) {
console.log('Image height is ' + info.height);
});
readableStream.pipe(transformer).pipe(writableStream);
```
#### metadata([callback])

@@ -53,2 +67,3 @@

* `channels`: Number of bands e.g. `3` for sRGB, `4` for CMYK
* `density`: Number of pixels per inch (DPI), if present
* `hasProfile`: Boolean indicating the presence of an embedded ICC profile

@@ -116,19 +131,33 @@ * `hasAlpha`: Boolean indicating the presence of an alpha transparency channel

#### crop([gravity])
#### crop([option])
Crop the resized image to the exact size specified, the default behaviour.
`gravity`, if present, is a String or an attribute of the `sharp.gravity` Object e.g. `sharp.gravity.north`.
`option`, if present, is an attribute of:
Possible values are `north`, `northeast`, `east`, `southeast`, `south`, `southwest`, `west`, `northwest`, `center` and `centre`.
The default gravity is `center`/`centre`.
* `sharp.gravity` e.g. `sharp.gravity.north`, to crop to an edge or corner, or
* `sharp.strategy` e.g. `sharp.strategy.entropy`, to crop dynamically.
Possible attributes of `sharp.gravity` are
`north`, `northeast`, `east`, `southeast`, `south`,
`southwest`, `west`, `northwest`, `center` and `centre`.
Possible attributes of the experimental `sharp.strategy` are:
* `entropy`: resize so one dimension is at its target size
then repeatedly remove pixels from the edge with the lowest
[Shannon entropy](https://en.wikipedia.org/wiki/Entropy_%28information_theory%29)
until it too reaches the target size.
The default crop option is a `center`/`centre` gravity.
```javascript
var transformer = sharp()
.resize(300, 200)
.crop(sharp.gravity.north)
.resize(200, 200)
.crop(sharp.strategy.entropy)
.on('error', function(err) {
console.log(err);
});
// Read image data from readableStream, resize and write image data to writableStream
// Read image data from readableStream
// Write 200px square auto-cropped image data to writableStream
readableStream.pipe(transformer).pipe(writableStream);

@@ -272,3 +301,3 @@ ```

Set the background for the `embed` and `flatten` operations.
Set the background for the `embed`, `flatten` and `extend` operations.

@@ -285,2 +314,21 @@ `rgba` is parsed by the [color](https://www.npmjs.org/package/color) module to extract values for red, green, blue and alpha.

#### extend(extension)
Extends/pads the edges of the image with `background`, where `extension` is one of:
* a Number representing the pixel count to add to each edge, or
* an Object containing `top`, `left`, `bottom` and `right` attributes, each a Number of pixels to add to that edge.
This operation will always occur after resizing and extraction, if any.
```javascript
// Resize to 140 pixels wide, then add 10 transparent pixels
// to the top, left and right edges and 20 to the bottom edge
sharp(input)
.resize(140)
.background({r: 0, g: 0, b: 0, a: 0})
.extend({top: 10, bottom: 20, left: 10, right: 10})
...
```
#### negate()

@@ -374,10 +422,15 @@

#### overlayWith(path)
#### overlayWith(image, [options])
_Experimental_
Overlay (composite) a image containing an alpha channel over the processed (resized, extracted etc.) image.
Alpha composite image at `path` over the processed (resized, extracted) image. The dimensions of the two images must match.
`image` is one of the following, and must be the same size or smaller than the processed image:
* `path` is a String containing the path to an image file with an alpha channel.
* Buffer containing PNG, WebP, GIF or SVG image data, or
* String containing the path to an image file, with most major transparency formats supported.
`options`, if present, is an Object with the following optional attributes:
* `gravity` is a String or an attribute of the `sharp.gravity` Object e.g. `sharp.gravity.north` at which to place the overlay, defaulting to `center`/`centre`.
```javascript

@@ -389,3 +442,3 @@ sharp('input.png')

.background('#ff6600')
.overlayWith('overlay.png')
.overlayWith('overlay.png', { gravity: sharp.gravity.southeast } )
.sharpen()

@@ -398,4 +451,4 @@ .withMetadata()

// outputBuffer contains upside down, 300px wide, alpha channel flattened
// onto orange background, composited with overlay.png, sharpened,
// with metadata, 90% quality WebP image data. Phew!
// onto orange background, composited with overlay.png with SE gravity,
// sharpened, with metadata, 90% quality WebP image data. Phew!
});

@@ -478,3 +531,3 @@ ```

* `orientation` is an integral Number between 0 and 7, used to update the value of the EXIF `Orientation` tag.
* `orientation` is an integral Number between 1 and 8, used to update the value of the EXIF `Orientation` tag.
This has no effect if the input image does not have an EXIF `Orientation` tag.

@@ -484,14 +537,21 @@

#### tile([size], [overlap])
#### tile(options)
The size and overlap, in pixels, of square Deep Zoom image pyramid tiles.
The size, overlap and directory layout to use when generating square Deep Zoom image pyramid tiles.
`options` is an Object with one or more of the following attributes:
* `size` is an integral Number between 1 and 8192. The default value is 256 pixels.
* `overlap` is an integral Number between 0 and 8192. The default value is 0 pixels.
* `layout` is a String, with value `dz`, `zoomify` or `google`. The default value is `dz`.
```javascript
sharp('input.tiff').tile(256).toFile('output.dzi', function(err, info) {
// The output.dzi file is the XML format Deep Zoom definition
// The output_files directory contains 256x256 pixel tiles grouped by zoom level
});
sharp('input.tiff')
.tile({
size: 512
})
.toFile('output.dzi', function(err, info) {
// output.dzi is the Deep Zoom XML definition
// output_files contains 512x512 tiles grouped by zoom level
});
```

@@ -498,0 +558,0 @@

# Changelog
### v0.14 - "*needle*"
Requires libvips v8.2.3
#### v0.14.0 - 2<sup>nd</sup> April 2016
* Add ability to extend (pad) the edges of an image.
[#128](https://github.com/lovell/sharp/issues/128)
[@blowsie](https://github.com/blowsie)
* Add support for Zoomify and Google tile layouts. Breaks existing tile API.
[#223](https://github.com/lovell/sharp/issues/223)
[@bdunnette](https://github.com/bdunnette)
* Improvements to overlayWith: differing sizes/formats, gravity, buffer input.
[#239](https://github.com/lovell/sharp/issues/239)
[@chrisriley](https://github.com/chrisriley)
* Add entropy-based crop strategy to remove least interesting edges.
[#295](https://github.com/lovell/sharp/issues/295)
[@rightaway](https://github.com/rightaway)
* Expose density metadata; set density of images from vector input.
[#338](https://github.com/lovell/sharp/issues/338)
[@lookfirst](https://github.com/lookfirst)
* Emit post-processing 'info' event for Stream output.
[#367](https://github.com/lovell/sharp/issues/367)
[@salzhrani](https://github.com/salzhrani)
* Ensure output image EXIF Orientation values are within 1-8 range.
[#385](https://github.com/lovell/sharp/pull/385)
[@jtobinisaniceguy](https://github.com/jtobinisaniceguy)
* Ensure ratios are not swapped when rotating 90/270 and ignoring aspect.
[#387](https://github.com/lovell/sharp/issues/387)
[@kleisauke](https://github.com/kleisauke)
### v0.13 - "*mind*"
Requires libvips v8.2.2
#### v0.13.1 - 27<sup>th</sup> February 2016

@@ -58,2 +98,4 @@

Requires libvips v8.2.0
#### v0.12.2 - 16<sup>th</sup> January 2016

@@ -60,0 +102,0 @@

@@ -17,3 +17,3 @@ # Installation

libvips and its dependencies are fetched and stored within `node_modules/sharp` during `npm install`.
libvips and its dependencies are fetched and stored within `node_modules/sharp/lib` during `npm install`.
This involves an automated HTTPS download of approximately 6MB.

@@ -30,5 +30,12 @@

* Raspbian Jessie
* Amazon Linux 2015.03, 2015.09
Preference will be given to an existing globally-installed (via `pkg-config`)
version of libvips that meets the minimum version requirement.
To use your own version of libvips instead of the provided binaries, make sure it is
at least the version listed under `config.libvips` in the `package.json` file that it
can be located using `pkg-config`. If you are using non-stadard paths (anything other
than `/usr` or `/usr/local`), you might need to set `PKG_CONFIG_PATH` during `npm install`
and `LD_LIBRARY_PATH` at runtime.
You can print the detected vips version using: `pkg-config --modversion vips-cpp`
This allows the use of newer versions of libvips with older versions of sharp.

@@ -118,2 +125,30 @@

### AWS Lambda
In order to use sharp on AWS Lambda, you need to [create a deployment package](http://docs.aws.amazon.com/lambda/latest/dg/nodejs-create-deployment-pkg.html). Because sharp
downloads and links libraries for the current platform during `npm install` you have to
do this on a system similar to the [Lambda Execution Environment](http://docs.aws.amazon.com/lambda/latest/dg/current-supported-versions.html). The easiest ways to do this, is to setup a
small t2.micro instance using the AMI ID listed in the previous link, ssh into it as ec2-user
and follow the instructions below.
Install depencies:
```sh
sudo yum-config-manager --enable epel
sudo yum install -y nodejs gcc-c++
curl -s https://www.npmjs.com/install.sh | sudo sh
```
Copy your code and package.json to the instance using `scp` and create a deployment package:
```sh
cd sharp-lambda-example
npm install
zip -ur9 ../sharp-lambda-example.zip index.js node_modules
```
You can now download your deployment ZIP using `scp` and upload it to Lambda.
**Performance Tip:** To get the best performance on Lambda choose the largest memory available because this also gives you the most cpu time (a 1536 MB function is 12x faster than a 128 MB function).
### Build tools

@@ -120,0 +155,0 @@

@@ -49,3 +49,3 @@ 'use strict';

limitInputPixels: maximum.pixels,
density: '72',
density: 72,
rawWidth: 0,

@@ -68,3 +68,3 @@ rawHeight: 0,

canvas: 'crop',
gravity: 0,
crop: 0,
angle: 0,

@@ -74,2 +74,6 @@ rotateBeforePreExtract: false,

flop: false,
extendTop: 0,
extendBottom: 0,
extendLeft: 0,
extendRight: 0,
withoutEnlargement: false,

@@ -90,3 +94,5 @@ interpolator: 'bicubic',

// overlay
overlayPath: '',
overlayFileIn: '',
overlayBufferIn: null,
overlayGravity: 0,
// output options

@@ -113,9 +119,9 @@ formatOut: 'input',

};
if (typeof input === 'string') {
if (isString(input)) {
// input=file
this.options.fileIn = input;
} else if (typeof input === 'object' && input instanceof Buffer) {
} else if (isBuffer(input)) {
// input=buffer
this.options.bufferIn = input;
} else if (typeof input === 'undefined' || input === null) {
} else if (!isDefined(input)) {
// input=stream

@@ -156,2 +162,8 @@ this.options.streamIn = true;

};
var isBuffer = function(val) {
return typeof val === 'object' && val instanceof Buffer;
};
var isString = function(val) {
return typeof val === 'string' && val.length > 0;
};
var isInteger = function(val) {

@@ -163,2 +175,5 @@ return typeof val === 'number' && !Number.isNaN(val) && val % 1 === 0;

};
var contains = function(val, list) {
return list.indexOf(val) !== -1;
};

@@ -174,3 +189,3 @@ /*

if (isInteger(options.density) && inRange(options.density, 1, 2400)) {
this.options.density = options.density.toString();
this.options.density = options.density;
} else {

@@ -227,26 +242,40 @@ throw new Error('Invalid density (1 to 2400) ' + options.density);

// Crop this part of the resized image (Center/Centre, North, East, South, West)
// Weighting to apply to image crop
module.exports.gravity = {
'center': 0,
'centre': 0,
'north': 1,
'east': 2,
'south': 3,
'west': 4,
'northeast': 5,
'southeast': 6,
'southwest': 7,
'northwest': 8
center: 0,
centre: 0,
north: 1,
east: 2,
south: 3,
west: 4,
northeast: 5,
southeast: 6,
southwest: 7,
northwest: 8
};
Sharp.prototype.crop = function(gravity) {
// Strategies for automagic behaviour
module.exports.strategy = {
entropy: 16
};
/*
What part of the image should be retained when cropping?
*/
Sharp.prototype.crop = function(crop) {
this.options.canvas = 'crop';
if (typeof gravity === 'undefined') {
this.options.gravity = module.exports.gravity.center;
} else if (typeof gravity === 'number' && !Number.isNaN(gravity) && gravity >= 0 && gravity <= 8) {
this.options.gravity = gravity;
} else if (typeof gravity === 'string' && typeof module.exports.gravity[gravity] === 'number') {
this.options.gravity = module.exports.gravity[gravity];
if (!isDefined(crop)) {
// Default
this.options.crop = module.exports.gravity.center;
} else if (isInteger(crop) && inRange(crop, 0, 8)) {
// Gravity (numeric)
this.options.crop = crop;
} else if (isString(crop) && isInteger(module.exports.gravity[crop])) {
// Gravity (string)
this.options.crop = module.exports.gravity[crop];
} else if (isInteger(crop) && crop === module.exports.strategy.entropy) {
// Strategy
this.options.crop = crop;
} else {
throw new Error('Unsupported crop gravity ' + gravity);
throw new Error('Unsupported crop ' + crop);
}

@@ -257,15 +286,6 @@ return this;

Sharp.prototype.extract = function(options) {
if (!options || typeof options !== 'object') {
// Legacy extract(top,left,width,height) syntax
options = {
left: arguments[1],
top: arguments[0],
width: arguments[2],
height: arguments[3]
};
}
var suffix = this.options.width === -1 && this.options.height === -1 ? 'Pre' : 'Post';
['left', 'top', 'width', 'height'].forEach(function (name) {
var value = options[name];
if (typeof value === 'number' && !Number.isNaN(value) && value % 1 === 0 && value >= 0) {
if (isInteger(value) && value >= 0) {
this.options[name + (name === 'left' || name === 'top' ? 'Offset' : '') + suffix] = value;

@@ -329,10 +349,22 @@ } else {

Sharp.prototype.overlayWith = function(overlayPath) {
if (typeof overlayPath !== 'string') {
throw new Error('The overlay path must be a string');
/*
Overlay with another image, using an optional gravity
*/
Sharp.prototype.overlayWith = function(overlay, options) {
if (isString(overlay)) {
this.options.overlayFileIn = overlay;
} else if (isBuffer(overlay)) {
this.options.overlayBufferIn = overlay;
} else {
throw new Error('Unsupported overlay ' + typeof overlay);
}
if (overlayPath === '') {
throw new Error('The overlay path cannot be empty');
if (isObject(options)) {
if (isInteger(options.gravity) && inRange(options.gravity, 0, 8)) {
this.options.overlayGravity = options.gravity;
} else if (isString(options.gravity) && isInteger(module.exports.gravity[options.gravity])) {
this.options.overlayGravity = module.exports.gravity[options.gravity];
} else if (isDefined(options.gravity)) {
throw new Error('Unsupported overlay gravity ' + options.gravity);
}
}
this.options.overlayPath = overlayPath;
return this;

@@ -606,8 +638,8 @@ };

withMetadata.orientation % 1 === 0 &&
withMetadata.orientation >= 0 &&
withMetadata.orientation <= 7
withMetadata.orientation >= 1 &&
withMetadata.orientation <= 8
) {
this.options.withMetadataOrientation = withMetadata.orientation;
} else {
throw new Error('Invalid orientation (0 to 7) ' + withMetadata.orientation);
throw new Error('Invalid orientation (1 to 8) ' + withMetadata.orientation);
}

@@ -620,23 +652,33 @@ }

/*
Tile size and overlap for Deep Zoom output
Tile-based deep zoom output options: size, overlap, layout
*/
Sharp.prototype.tile = function(size, overlap) {
// Size of square tiles, in pixels
if (typeof size !== 'undefined' && size !== null) {
if (!Number.isNaN(size) && size % 1 === 0 && size >= 1 && size <= 8192) {
this.options.tileSize = size;
} else {
throw new Error('Invalid tile size (1 to 8192) ' + size);
Sharp.prototype.tile = function(tile) {
if (isObject(tile)) {
// Size of square tiles, in pixels
if (isDefined(tile.size)) {
if (isInteger(tile.size) && inRange(tile.size, 1, 8192)) {
this.options.tileSize = tile.size;
} else {
throw new Error('Invalid tile size (1 to 8192) ' + tile.size);
}
}
}
// Overlap of tiles, in pixels
if (typeof overlap !== 'undefined' && overlap !== null) {
if (!Number.isNaN(overlap) && overlap % 1 === 0 && overlap >= 0 && overlap <= 8192) {
if (overlap > this.options.tileSize) {
throw new Error('Tile overlap ' + overlap + ' cannot be larger than tile size ' + this.options.tileSize);
// Overlap of tiles, in pixels
if (isDefined(tile.overlap)) {
if (isInteger(tile.overlap) && inRange(tile.overlap, 0, 8192)) {
if (tile.overlap > this.options.tileSize) {
throw new Error('Tile overlap ' + tile.overlap + ' cannot be larger than tile size ' + this.options.tileSize);
}
this.options.tileOverlap = tile.overlap;
} else {
throw new Error('Invalid tile overlap (0 to 8192) ' + tile.overlap);
}
this.options.tileOverlap = overlap;
} else {
throw new Error('Invalid tile overlap (0 to 8192) ' + overlap);
}
// Layout
if (isDefined(tile.layout)) {
if (isString(tile.layout) && contains(tile.layout, ['dz', 'google', 'zoomify'])) {
this.options.tileLayout = tile.layout;
} else {
throw new Error('Invalid tile layout ' + tile.layout);
}
}
}

@@ -646,2 +688,28 @@ return this;

/*
Extend edges
*/
Sharp.prototype.extend = function(extend) {
if (isInteger(extend) && extend > 0) {
this.options.extendTop = extend;
this.options.extendBottom = extend;
this.options.extendLeft = extend;
this.options.extendRight = extend;
} else if (
isObject(extend) &&
isInteger(extend.top) && extend.top >= 0 &&
isInteger(extend.bottom) && extend.bottom >= 0 &&
isInteger(extend.left) && extend.left >= 0 &&
isInteger(extend.right) && extend.right >= 0
) {
this.options.extendTop = extend.top;
this.options.extendBottom = extend.bottom;
this.options.extendLeft = extend.left;
this.options.extendRight = extend.right;
} else {
throw new Error('Invalid edge extension ' + extend);
}
return this;
};
Sharp.prototype.resize = function(width, height) {

@@ -800,6 +868,7 @@ if (!width) {

this.on('finish', function() {
sharp.pipeline(that.options, function(err, data) {
sharp.pipeline(that.options, function(err, data, info) {
if (err) {
that.emit('error', err);
} else {
that.emit('info', info);
that.push(data);

@@ -812,6 +881,7 @@ }

// output=stream, input=file/buffer
sharp.pipeline(this.options, function(err, data) {
sharp.pipeline(this.options, function(err, data, info) {
if (err) {
that.emit('error', err);
} else {
that.emit('info', info);
that.push(data);

@@ -818,0 +888,0 @@ }

{
"name": "sharp",
"version": "0.13.1",
"version": "0.14.0",
"author": "Lovell Fuller <npm@lovell.info>",

@@ -21,3 +21,4 @@ "contributors": [

"Chris Riley <criley@primedia.com>",
"David Carley <dacarley@gmail.com>"
"David Carley <dacarley@gmail.com>",
"John Tobin <john@limelightmobileinc.com>"
],

@@ -51,5 +52,5 @@ "description": "High performance Node.js module to resize JPEG, PNG, WebP and TIFF images using the libvips library",

"dependencies": {
"bluebird": "^3.3.3",
"bluebird": "^3.3.4",
"color": "^0.11.1",
"nan": "^2.2.0",
"nan": "^2.2.1",
"semver": "^5.1.0",

@@ -61,3 +62,3 @@ "request": "^2.69.0",

"async": "^1.5.2",
"coveralls": "^2.11.8",
"coveralls": "^2.11.9",
"exif-reader": "^1.0.0",

@@ -74,3 +75,3 @@ "icc": "^0.0.2",

"config": {
"libvips": "8.2.2"
"libvips": "8.2.3"
},

@@ -77,0 +78,0 @@ "engines": {

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

SocketSocket SOC 2 Logo

Product

  • Package Alerts
  • Integrations
  • Docs
  • Pricing
  • FAQ
  • Roadmap
  • Changelog

Packages

npm

Stay in touch

Get open source security insights delivered straight into your inbox.


  • Terms
  • Privacy
  • Security

Made with ⚡️ by Socket Inc