mirror of
https://github.com/lovell/sharp.git
synced 2025-07-09 10:30:15 +02:00
Expose libvips interpolators #69
This commit is contained in:
parent
6498fc3a9e
commit
017bf1e905
64
README.md
64
README.md
@ -110,21 +110,33 @@ image.metadata(function(err, metadata) {
|
|||||||
```
|
```
|
||||||
|
|
||||||
```javascript
|
```javascript
|
||||||
var pipeline = sharp().rotate().resize(null, 200).progressive().toBuffer(function(err, outputBuffer, info) {
|
var pipeline = sharp()
|
||||||
if (err) {
|
.rotate()
|
||||||
throw err;
|
.resize(null, 200)
|
||||||
}
|
.progressive()
|
||||||
// outputBuffer contains 200px high progressive JPEG image data, auto-rotated using EXIF Orientation tag
|
.toBuffer(function(err, outputBuffer, info) {
|
||||||
// info.width and info.height contain the final pixel dimensions of the resized image
|
if (err) {
|
||||||
});
|
throw err;
|
||||||
|
}
|
||||||
|
// outputBuffer contains 200px high progressive JPEG image data,
|
||||||
|
// auto-rotated using EXIF Orientation tag
|
||||||
|
// info.width and info.height contain the dimensions of the resized image
|
||||||
|
});
|
||||||
readableStream.pipe(pipeline);
|
readableStream.pipe(pipeline);
|
||||||
```
|
```
|
||||||
|
|
||||||
```javascript
|
```javascript
|
||||||
sharp('input.png').rotate(180).resize(300).sharpen().quality(90).webp().toBuffer().then(function(outputBuffer, info) {
|
sharp('input.png')
|
||||||
// outputBuffer contains 300px wide, upside down, sharpened, 90% quality WebP image data
|
.rotate(180)
|
||||||
// info.width and info.height contain the final pixel dimensions of the resized image
|
.resize(300)
|
||||||
});
|
.sharpen()
|
||||||
|
.quality(90)
|
||||||
|
.webp()
|
||||||
|
.toBuffer()
|
||||||
|
.then(function(outputBuffer) {
|
||||||
|
// outputBuffer contains 300px wide, upside down, sharpened,
|
||||||
|
// 90% quality WebP image data
|
||||||
|
});
|
||||||
```
|
```
|
||||||
|
|
||||||
```javascript
|
```javascript
|
||||||
@ -137,10 +149,16 @@ http.createServer(function(request, response) {
|
|||||||
```
|
```
|
||||||
|
|
||||||
```javascript
|
```javascript
|
||||||
sharp(inputBuffer).resize(200, 300).bicubicInterpolation().embedWhite().toFile('output.tiff').then(function() {
|
sharp(inputBuffer)
|
||||||
// output.tiff is a 200 pixels wide and 300 pixels high image containing a bicubic scaled
|
.resize(200, 300)
|
||||||
// version, embedded on a white canvas, of the image data in buffer
|
.interpolateWith(sharp.interpolator.nohalo)
|
||||||
});
|
.embedWhite()
|
||||||
|
.toFile('output.tiff')
|
||||||
|
.then(function() {
|
||||||
|
// output.tiff is a 200 pixels wide and 300 pixels high image
|
||||||
|
// containing a bicubic scaled version, embedded on a white canvas,
|
||||||
|
// of the image data in inputBuffer
|
||||||
|
});
|
||||||
```
|
```
|
||||||
|
|
||||||
```javascript
|
```javascript
|
||||||
@ -247,17 +265,17 @@ This is equivalent to GraphicsMagick's `>` geometry option: "change the dimensio
|
|||||||
|
|
||||||
Perform a mild sharpen of the resultant image. This typically reduces performance by 30%.
|
Perform a mild sharpen of the resultant image. This typically reduces performance by 30%.
|
||||||
|
|
||||||
#### bilinearInterpolation()
|
#### interpolateWith(interpolator)
|
||||||
|
|
||||||
Use [bilinear interpolation](http://en.wikipedia.org/wiki/Bilinear_interpolation) for image resizing, the default (and fastest) interpolation if none is specified.
|
Use the given interpolator for image resizing, where `interpolator` is an attribute of the `sharp.interpolator` Object e.g. `sharp.interpolator.bicubic`.
|
||||||
|
|
||||||
#### bicubicInterpolation()
|
Possible interpolators, in order of performance, are:
|
||||||
|
|
||||||
Use [bicubic interpolation](http://en.wikipedia.org/wiki/Bicubic_interpolation) for image resizing. This typically reduces performance by 5%.
|
* `bilinear`: Use [bilinear interpolation](http://en.wikipedia.org/wiki/Bilinear_interpolation), the default (and fastest) interpolation.
|
||||||
|
* `bicubic`: Use [bicubic interpolation](http://en.wikipedia.org/wiki/Bicubic_interpolation), which typically reduces performance by 5%.
|
||||||
#### nohaloInterpolation()
|
* `vertexSplitQuadraticBasisSpline`: Use [VSQBS interpolation](https://github.com/jcupitt/libvips/blob/master/libvips/resample/vsqbs.cpp#L48), which prevents "staircasing" when enlarging and typically reduces performance by 5%.
|
||||||
|
* `locallyBoundedBicubic`: Use [LBB interpolation](https://github.com/jcupitt/libvips/blob/master/libvips/resample/lbb.cpp#L100), which prevents some "[acutance](http://en.wikipedia.org/wiki/Acutance)" and typically reduces performance by a factor of 2.
|
||||||
Use [Nohalo interpolation](http://eprints.soton.ac.uk/268086/) for image resizing. This typically reduces performance by a factor of 2.
|
* `nohalo`: Use [Nohalo interpolation](http://eprints.soton.ac.uk/268086/), which prevents acutance and typically reduces performance by a factor of 3.
|
||||||
|
|
||||||
### Output options
|
### Output options
|
||||||
|
|
||||||
|
36
index.js
36
index.js
@ -135,28 +135,32 @@ Sharp.prototype.sharpen = function(sharpen) {
|
|||||||
};
|
};
|
||||||
|
|
||||||
/*
|
/*
|
||||||
Use bilinear interpolation for the affine transformation (fastest, default)
|
Set the interpolator to use for the affine transformation
|
||||||
*/
|
*/
|
||||||
Sharp.prototype.bilinearInterpolation = function() {
|
module.exports.interpolator = {
|
||||||
this.options.interpolator = 'bilinear';
|
bilinear: 'bilinear',
|
||||||
|
bicubic: 'bicubic',
|
||||||
|
nohalo: 'nohalo',
|
||||||
|
locallyBoundedBicubic: 'lbb',
|
||||||
|
vertexSplitQuadraticBasisSpline: 'vsqbs'
|
||||||
|
};
|
||||||
|
Sharp.prototype.interpolateWith = function(interpolator) {
|
||||||
|
this.options.interpolator = interpolator;
|
||||||
return this;
|
return this;
|
||||||
};
|
};
|
||||||
|
|
||||||
/*
|
/*
|
||||||
Use bicubic interpolation for the affine transformation
|
Deprecated interpolation methods, to be removed in v0.7.0
|
||||||
*/
|
*/
|
||||||
Sharp.prototype.bicubicInterpolation = function() {
|
Sharp.prototype.bilinearInterpolation = util.deprecate(function() {
|
||||||
this.options.interpolator = 'bicubic';
|
return this.interpolateWith(module.exports.interpolator.bilinear);
|
||||||
return this;
|
}, 'bilinearInterpolation() is deprecated, use interpolateWith(sharp.interpolator.bilinear) instead');
|
||||||
};
|
Sharp.prototype.bicubicInterpolation = util.deprecate(function() {
|
||||||
|
return this.interpolateWith(module.exports.interpolator.bicubic);
|
||||||
/*
|
}, 'bicubicInterpolation() is deprecated, use interpolateWith(sharp.interpolator.bicubic) instead');
|
||||||
Use Nohalo interpolation for the affine transformation
|
Sharp.prototype.nohaloInterpolation = util.deprecate(function() {
|
||||||
*/
|
return this.interpolateWith(module.exports.interpolator.nohalo);
|
||||||
Sharp.prototype.nohaloInterpolation = function() {
|
}, 'nohaloInterpolation() is deprecated, use interpolateWith(sharp.interpolator.nohalo) instead');
|
||||||
this.options.interpolator = 'nohalo';
|
|
||||||
return this;
|
|
||||||
};
|
|
||||||
|
|
||||||
Sharp.prototype.progressive = function(progressive) {
|
Sharp.prototype.progressive = function(progressive) {
|
||||||
this.options.progressive = (typeof progressive === 'boolean') ? progressive : true;
|
this.options.progressive = (typeof progressive === 'boolean') ? progressive : true;
|
||||||
|
@ -188,7 +188,7 @@ async.series({
|
|||||||
}).add("sharp-file-buffer-bicubic", {
|
}).add("sharp-file-buffer-bicubic", {
|
||||||
defer: true,
|
defer: true,
|
||||||
fn: function(deferred) {
|
fn: function(deferred) {
|
||||||
sharp(inputJpg).resize(width, height).bicubicInterpolation().toBuffer(function(err, buffer) {
|
sharp(inputJpg).resize(width, height).interpolateWith(sharp.interpolator.bicubic).toBuffer(function(err, buffer) {
|
||||||
if (err) {
|
if (err) {
|
||||||
throw err;
|
throw err;
|
||||||
} else {
|
} else {
|
||||||
@ -200,7 +200,31 @@ async.series({
|
|||||||
}).add("sharp-file-buffer-nohalo", {
|
}).add("sharp-file-buffer-nohalo", {
|
||||||
defer: true,
|
defer: true,
|
||||||
fn: function(deferred) {
|
fn: function(deferred) {
|
||||||
sharp(inputJpg).resize(width, height).nohaloInterpolation().toBuffer(function(err, buffer) {
|
sharp(inputJpg).resize(width, height).interpolateWith(sharp.interpolator.nohalo).toBuffer(function(err, buffer) {
|
||||||
|
if (err) {
|
||||||
|
throw err;
|
||||||
|
} else {
|
||||||
|
assert.notStrictEqual(null, buffer);
|
||||||
|
deferred.resolve();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}).add("sharp-file-buffer-locallyBoundedBicubic", {
|
||||||
|
defer: true,
|
||||||
|
fn: function(deferred) {
|
||||||
|
sharp(inputJpg).resize(width, height).interpolateWith(sharp.interpolator.locallyBoundedBicubic).toBuffer(function(err, buffer) {
|
||||||
|
if (err) {
|
||||||
|
throw err;
|
||||||
|
} else {
|
||||||
|
assert.notStrictEqual(null, buffer);
|
||||||
|
deferred.resolve();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}).add("sharp-file-buffer-vertexSplitQuadraticBasisSpline", {
|
||||||
|
defer: true,
|
||||||
|
fn: function(deferred) {
|
||||||
|
sharp(inputJpg).resize(width, height).interpolateWith(sharp.interpolator.vertexSplitQuadraticBasisSpline).toBuffer(function(err, buffer) {
|
||||||
if (err) {
|
if (err) {
|
||||||
throw err;
|
throw err;
|
||||||
} else {
|
} else {
|
||||||
|
@ -249,7 +249,7 @@ async.series([
|
|||||||
},
|
},
|
||||||
// Interpolation: bilinear
|
// Interpolation: bilinear
|
||||||
function(done) {
|
function(done) {
|
||||||
sharp(inputJpg).resize(320, 240).bilinearInterpolation().toBuffer(function(err, data, info) {
|
sharp(inputJpg).resize(320, 240).interpolateWith(sharp.interpolator.bilinear).toBuffer(function(err, data, info) {
|
||||||
if (err) throw err;
|
if (err) throw err;
|
||||||
assert.strictEqual(true, data.length > 0);
|
assert.strictEqual(true, data.length > 0);
|
||||||
assert.strictEqual(320, info.width);
|
assert.strictEqual(320, info.width);
|
||||||
@ -259,7 +259,7 @@ async.series([
|
|||||||
},
|
},
|
||||||
// Interpolation: bicubic
|
// Interpolation: bicubic
|
||||||
function(done) {
|
function(done) {
|
||||||
sharp(inputJpg).resize(320, 240).bicubicInterpolation().toBuffer(function(err, data, info) {
|
sharp(inputJpg).resize(320, 240).interpolateWith(sharp.interpolator.bicubic).toBuffer(function(err, data, info) {
|
||||||
if (err) throw err;
|
if (err) throw err;
|
||||||
assert.strictEqual(true, data.length > 0);
|
assert.strictEqual(true, data.length > 0);
|
||||||
assert.strictEqual(320, info.width);
|
assert.strictEqual(320, info.width);
|
||||||
@ -269,7 +269,27 @@ async.series([
|
|||||||
},
|
},
|
||||||
// Interpolation: nohalo
|
// Interpolation: nohalo
|
||||||
function(done) {
|
function(done) {
|
||||||
sharp(inputJpg).resize(320, 240).nohaloInterpolation().toBuffer(function(err, data, info) {
|
sharp(inputJpg).resize(320, 240).interpolateWith(sharp.interpolator.nohalo).toBuffer(function(err, data, info) {
|
||||||
|
if (err) throw err;
|
||||||
|
assert.strictEqual(true, data.length > 0);
|
||||||
|
assert.strictEqual(320, info.width);
|
||||||
|
assert.strictEqual(240, info.height);
|
||||||
|
done();
|
||||||
|
});
|
||||||
|
},
|
||||||
|
// Interpolation: locally bounded bicubic (LBB)
|
||||||
|
function(done) {
|
||||||
|
sharp(inputJpg).resize(320, 240).interpolateWith(sharp.interpolator.locallyBoundedBicubic).toBuffer(function(err, data, info) {
|
||||||
|
if (err) throw err;
|
||||||
|
assert.strictEqual(true, data.length > 0);
|
||||||
|
assert.strictEqual(320, info.width);
|
||||||
|
assert.strictEqual(240, info.height);
|
||||||
|
done();
|
||||||
|
});
|
||||||
|
},
|
||||||
|
// Interpolation: vertex split quadratic basis spline (VSQBS)
|
||||||
|
function(done) {
|
||||||
|
sharp(inputJpg).resize(320, 240).interpolateWith(sharp.interpolator.vertexSplitQuadraticBasisSpline).toBuffer(function(err, data, info) {
|
||||||
if (err) throw err;
|
if (err) throw err;
|
||||||
assert.strictEqual(true, data.length > 0);
|
assert.strictEqual(true, data.length > 0);
|
||||||
assert.strictEqual(320, info.width);
|
assert.strictEqual(320, info.width);
|
||||||
@ -346,7 +366,7 @@ async.series([
|
|||||||
});
|
});
|
||||||
});
|
});
|
||||||
var pipeline = sharp().resize(320, 240);
|
var pipeline = sharp().resize(320, 240);
|
||||||
readable.pipe(pipeline).pipe(writable)
|
readable.pipe(pipeline).pipe(writable);
|
||||||
},
|
},
|
||||||
// Crop, gravity=north
|
// Crop, gravity=north
|
||||||
function(done) {
|
function(done) {
|
||||||
@ -516,7 +536,7 @@ async.series([
|
|||||||
assert.strictEqual(1362, info.width);
|
assert.strictEqual(1362, info.width);
|
||||||
assert.strictEqual(1112, info.height);
|
assert.strictEqual(1112, info.height);
|
||||||
done();
|
done();
|
||||||
})
|
});
|
||||||
});
|
});
|
||||||
},
|
},
|
||||||
// Verify internal counters
|
// Verify internal counters
|
||||||
|
Loading…
x
Reference in New Issue
Block a user