mirror of
https://github.com/lovell/sharp.git
synced 2026-02-07 23:26:15 +01:00
Compare commits
5 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
740838b47c | ||
|
|
f7c2a839ad | ||
|
|
62fcfb3dba | ||
|
|
333e8789f4 | ||
|
|
3a9a137f40 |
@@ -74,7 +74,7 @@ The _gettext_ dependency of _libvips_ [can lead](https://github.com/lovell/sharp
|
|||||||
|
|
||||||
### Using with gulp.js
|
### Using with gulp.js
|
||||||
|
|
||||||
[Mohammad Prabowo](https://github.com/rizalp) maintains a [gulp.js plugin](https://github.com/rizalp/gulp-sharp).
|
[Eugeny Vlasenko](https://github.com/mahnunchik) maintains [gulp-responsive](https://www.npmjs.org/package/gulp-responsive) and [Mohammad Prabowo](https://github.com/rizalp) maintains [gulp-sharp](https://www.npmjs.org/package/gulp-sharp).
|
||||||
|
|
||||||
## Usage examples
|
## Usage examples
|
||||||
|
|
||||||
|
|||||||
BIN
icc/USWebCoatedSWOP.icc
Normal file
BIN
icc/USWebCoatedSWOP.icc
Normal file
Binary file not shown.
3
index.js
3
index.js
@@ -1,5 +1,6 @@
|
|||||||
'use strict';
|
'use strict';
|
||||||
|
|
||||||
|
var path = require('path');
|
||||||
var util = require('util');
|
var util = require('util');
|
||||||
var stream = require('stream');
|
var stream = require('stream');
|
||||||
|
|
||||||
@@ -17,6 +18,8 @@ var Sharp = function(input) {
|
|||||||
// input options
|
// input options
|
||||||
streamIn: false,
|
streamIn: false,
|
||||||
sequentialRead: false,
|
sequentialRead: false,
|
||||||
|
// ICC profile to use when input CMYK image has no embedded profile
|
||||||
|
iccProfileCmyk: path.join(__dirname, 'icc', 'USWebCoatedSWOP.icc'),
|
||||||
// resize options
|
// resize options
|
||||||
topOffsetPre: -1,
|
topOffsetPre: -1,
|
||||||
leftOffsetPre: -1,
|
leftOffsetPre: -1,
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"name": "sharp",
|
"name": "sharp",
|
||||||
"version": "0.7.1",
|
"version": "0.7.2",
|
||||||
"author": "Lovell Fuller <npm@lovell.info>",
|
"author": "Lovell Fuller <npm@lovell.info>",
|
||||||
"contributors": [
|
"contributors": [
|
||||||
"Pierre Inglebert <pierre.inglebert@gmail.com>",
|
"Pierre Inglebert <pierre.inglebert@gmail.com>",
|
||||||
@@ -41,9 +41,9 @@
|
|||||||
"stream"
|
"stream"
|
||||||
],
|
],
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"bluebird": "^2.3.9",
|
"bluebird": "^2.3.10",
|
||||||
"color": "^0.7.1",
|
"color": "^0.7.1",
|
||||||
"nan": "^1.3.0"
|
"nan": "^1.4.0"
|
||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"mocha": "^2.0.1",
|
"mocha": "^2.0.1",
|
||||||
|
|||||||
@@ -1,5 +1,6 @@
|
|||||||
#include <tuple>
|
#include <tuple>
|
||||||
#include <math.h>
|
#include <algorithm>
|
||||||
|
#include <cmath>
|
||||||
#include <node.h>
|
#include <node.h>
|
||||||
#include <node_buffer.h>
|
#include <node_buffer.h>
|
||||||
#include <vips/vips.h>
|
#include <vips/vips.h>
|
||||||
@@ -29,6 +30,7 @@ struct ResizeBaton {
|
|||||||
std::string fileIn;
|
std::string fileIn;
|
||||||
void* bufferIn;
|
void* bufferIn;
|
||||||
size_t bufferInLength;
|
size_t bufferInLength;
|
||||||
|
std::string iccProfileCmyk;
|
||||||
std::string output;
|
std::string output;
|
||||||
std::string outputFormat;
|
std::string outputFormat;
|
||||||
void* bufferOut;
|
void* bufferOut;
|
||||||
@@ -70,7 +72,6 @@ struct ResizeBaton {
|
|||||||
topOffsetPost(-1),
|
topOffsetPost(-1),
|
||||||
canvas(CROP),
|
canvas(CROP),
|
||||||
gravity(0),
|
gravity(0),
|
||||||
background{0.0, 0.0, 0.0, 255.0},
|
|
||||||
flatten(false),
|
flatten(false),
|
||||||
sharpen(false),
|
sharpen(false),
|
||||||
gamma(0.0),
|
gamma(0.0),
|
||||||
@@ -79,7 +80,12 @@ struct ResizeBaton {
|
|||||||
flop(false),
|
flop(false),
|
||||||
progressive(false),
|
progressive(false),
|
||||||
withoutEnlargement(false),
|
withoutEnlargement(false),
|
||||||
withMetadata(false) {}
|
withMetadata(false) {
|
||||||
|
background[0] = 0.0;
|
||||||
|
background[1] = 0.0;
|
||||||
|
background[2] = 0.0;
|
||||||
|
background[3] = 255.0;
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
class ResizeWorker : public NanAsyncWorker {
|
class ResizeWorker : public NanAsyncWorker {
|
||||||
@@ -231,16 +237,28 @@ class ResizeWorker : public NanAsyncWorker {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Handle colour profile, if any, for non sRGB images
|
// Handle colour profile, if any, for non sRGB images
|
||||||
if (image->Type != VIPS_INTERPRETATION_sRGB && vips_image_get_typeof(image, VIPS_META_ICC_NAME)) {
|
if (image->Type != VIPS_INTERPRETATION_sRGB) {
|
||||||
// Import embedded profile
|
// Get the input colour profile
|
||||||
VipsImage *profile = vips_image_new();
|
if (vips_image_get_typeof(image, VIPS_META_ICC_NAME)) {
|
||||||
vips_object_local(hook, profile);
|
// Use embedded profile
|
||||||
if (vips_icc_import(image, &profile, NULL, "embedded", TRUE, "pcs", VIPS_PCS_XYZ, NULL)) {
|
VipsImage *profile = vips_image_new();
|
||||||
return Error(baton, hook);
|
vips_object_local(hook, profile);
|
||||||
|
if (vips_icc_import(image, &profile, "pcs", VIPS_PCS_XYZ, "embedded", TRUE, NULL)) {
|
||||||
|
return Error(baton, hook);
|
||||||
|
}
|
||||||
|
g_object_unref(image);
|
||||||
|
image = profile;
|
||||||
|
} else if (image->Type == VIPS_INTERPRETATION_CMYK) {
|
||||||
|
// CMYK with no embedded profile
|
||||||
|
VipsImage *profile = vips_image_new();
|
||||||
|
vips_object_local(hook, profile);
|
||||||
|
if (vips_icc_import(image, &profile, "pcs", VIPS_PCS_XYZ, "input_profile", (baton->iccProfileCmyk).c_str(), NULL)) {
|
||||||
|
return Error(baton, hook);
|
||||||
|
}
|
||||||
|
g_object_unref(image);
|
||||||
|
image = profile;
|
||||||
}
|
}
|
||||||
g_object_unref(image);
|
// Attempt to convert to sRGB colour space
|
||||||
image = profile;
|
|
||||||
// Convert to sRGB colour space
|
|
||||||
VipsImage *colourspaced = vips_image_new();
|
VipsImage *colourspaced = vips_image_new();
|
||||||
vips_object_local(hook, colourspaced);
|
vips_object_local(hook, colourspaced);
|
||||||
if (vips_colourspace(image, &colourspaced, VIPS_INTERPRETATION_sRGB, NULL)) {
|
if (vips_colourspace(image, &colourspaced, VIPS_INTERPRETATION_sRGB, NULL)) {
|
||||||
@@ -639,7 +657,10 @@ class ResizeWorker : public NanAsyncWorker {
|
|||||||
bool flip = FALSE;
|
bool flip = FALSE;
|
||||||
if (angle == -1) {
|
if (angle == -1) {
|
||||||
const char *exif;
|
const char *exif;
|
||||||
if (!vips_image_get_string(input, "exif-ifd0-Orientation", &exif)) {
|
if (
|
||||||
|
vips_image_get_typeof(input, "exif-ifd0-Orientation") != 0 &&
|
||||||
|
!vips_image_get_string(input, "exif-ifd0-Orientation", &exif)
|
||||||
|
) {
|
||||||
if (exif[0] == 0x36) { // "6"
|
if (exif[0] == 0x36) { // "6"
|
||||||
rotate = ANGLE_90;
|
rotate = ANGLE_90;
|
||||||
} else if (exif[0] == 0x33) { // "3"
|
} else if (exif[0] == 0x33) { // "3"
|
||||||
@@ -733,6 +754,8 @@ NAN_METHOD(resize) {
|
|||||||
baton->bufferInLength = node::Buffer::Length(buffer);
|
baton->bufferInLength = node::Buffer::Length(buffer);
|
||||||
baton->bufferIn = node::Buffer::Data(buffer);
|
baton->bufferIn = node::Buffer::Data(buffer);
|
||||||
}
|
}
|
||||||
|
// ICC profile to use when input CMYK image has no embedded profile
|
||||||
|
baton->iccProfileCmyk = *String::Utf8Value(options->Get(NanNew<String>("iccProfileCmyk"))->ToString());
|
||||||
// Extract image options
|
// Extract image options
|
||||||
baton->topOffsetPre = options->Get(NanNew<String>("topOffsetPre"))->Int32Value();
|
baton->topOffsetPre = options->Get(NanNew<String>("topOffsetPre"))->Int32Value();
|
||||||
baton->leftOffsetPre = options->Get(NanNew<String>("leftOffsetPre"))->Int32Value();
|
baton->leftOffsetPre = options->Get(NanNew<String>("leftOffsetPre"))->Int32Value();
|
||||||
|
|||||||
BIN
test/fixtures/Channel_digital_image_CMYK_color_no_profile.jpg
vendored
Normal file
BIN
test/fixtures/Channel_digital_image_CMYK_color_no_profile.jpg
vendored
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 135 KiB |
1
test/fixtures/index.js
vendored
1
test/fixtures/index.js
vendored
@@ -13,6 +13,7 @@ module.exports = {
|
|||||||
inputJpgWithExifMirroring: getPath('Landscape_5.jpg'), // https://github.com/recurser/exif-orientation-examples/blob/master/Landscape_5.jpg
|
inputJpgWithExifMirroring: getPath('Landscape_5.jpg'), // https://github.com/recurser/exif-orientation-examples/blob/master/Landscape_5.jpg
|
||||||
inputJpgWithGammaHoliness: getPath('gamma_dalai_lama_gray.jpg'), // http://www.4p8.com/eric.brasseur/gamma.html
|
inputJpgWithGammaHoliness: getPath('gamma_dalai_lama_gray.jpg'), // http://www.4p8.com/eric.brasseur/gamma.html
|
||||||
inputJpgWithCmykProfile: getPath('Channel_digital_image_CMYK_color.jpg'), // http://en.wikipedia.org/wiki/File:Channel_digital_image_CMYK_color.jpg
|
inputJpgWithCmykProfile: getPath('Channel_digital_image_CMYK_color.jpg'), // http://en.wikipedia.org/wiki/File:Channel_digital_image_CMYK_color.jpg
|
||||||
|
inputJpgWithCmykNoProfile: getPath('Channel_digital_image_CMYK_color_no_profile.jpg'),
|
||||||
|
|
||||||
inputPng: getPath('50020484-00001.png'), // http://c.searspartsdirect.com/lis_png/PLDM/50020484-00001.png
|
inputPng: getPath('50020484-00001.png'), // http://c.searspartsdirect.com/lis_png/PLDM/50020484-00001.png
|
||||||
inputPngWithTransparency: getPath('blackbug.png'), // public domain
|
inputPngWithTransparency: getPath('blackbug.png'), // public domain
|
||||||
|
|||||||
@@ -66,4 +66,16 @@ describe('Colour space conversion', function() {
|
|||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
|
it('From profile-less CMYK to sRGB', function(done) {
|
||||||
|
sharp(fixtures.inputJpgWithCmykNoProfile)
|
||||||
|
.resize(320)
|
||||||
|
.toBuffer(function(err, data, info) {
|
||||||
|
if (err) throw err;
|
||||||
|
assert.strictEqual(true, data.length > 0);
|
||||||
|
assert.strictEqual('jpeg', info.format);
|
||||||
|
assert.strictEqual(320, info.width);
|
||||||
|
done();
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
});
|
});
|
||||||
|
|||||||
@@ -68,6 +68,21 @@ describe('Rotation', function() {
|
|||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
|
it('Attempt to auto-rotate image format without EXIF support', function(done) {
|
||||||
|
sharp(fixtures.inputGif)
|
||||||
|
.rotate()
|
||||||
|
.resize(320)
|
||||||
|
.jpeg()
|
||||||
|
.toBuffer(function(err, data, info) {
|
||||||
|
if (err) throw err;
|
||||||
|
assert.strictEqual(true, data.length > 0);
|
||||||
|
assert.strictEqual('jpeg', info.format);
|
||||||
|
assert.strictEqual(320, info.width);
|
||||||
|
assert.strictEqual(213, info.height);
|
||||||
|
done();
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
it('Rotate to an invalid angle, should fail', function(done) {
|
it('Rotate to an invalid angle, should fail', function(done) {
|
||||||
var fail = false;
|
var fail = false;
|
||||||
try {
|
try {
|
||||||
|
|||||||
Reference in New Issue
Block a user