mirror of
https://github.com/lovell/sharp.git
synced 2025-07-09 18:40:16 +02:00
Merge pull request #18 from pierreinglebert/master
Add 'max' canvas option to specify the maximum width and/or height. Approximately equivalent to GraphicsMagick's geometry option.
This commit is contained in:
commit
ad7735a0a6
@ -143,6 +143,10 @@ Scale to `width` x `height`. By default, the resized image is cropped to the exa
|
|||||||
|
|
||||||
Crop the resized image to the exact size specified, the default behaviour.
|
Crop the resized image to the exact size specified, the default behaviour.
|
||||||
|
|
||||||
|
### max()
|
||||||
|
|
||||||
|
Preserving aspect ratio, resize the image to the maximum width or height specified.
|
||||||
|
|
||||||
### embedWhite()
|
### embedWhite()
|
||||||
|
|
||||||
Embed the resized image on a white background of the exact size specified.
|
Embed the resized image on a white background of the exact size specified.
|
||||||
|
6
index.js
6
index.js
@ -44,6 +44,12 @@ Sharp.prototype.embedBlack = function() {
|
|||||||
return this;
|
return this;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
Sharp.prototype.max = function() {
|
||||||
|
this.options.canvas = 'm';
|
||||||
|
return this;
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
Sharp.prototype.sharpen = function(sharpen) {
|
Sharp.prototype.sharpen = function(sharpen) {
|
||||||
this.options.sharpen = (typeof sharpen === 'boolean') ? sharpen : true;
|
this.options.sharpen = (typeof sharpen === 'boolean') ? sharpen : true;
|
||||||
return this;
|
return this;
|
||||||
|
16
src/sharp.cc
16
src/sharp.cc
@ -20,6 +20,7 @@ struct resize_baton {
|
|||||||
int width;
|
int width;
|
||||||
int height;
|
int height;
|
||||||
bool crop;
|
bool crop;
|
||||||
|
bool max;
|
||||||
VipsExtend extend;
|
VipsExtend extend;
|
||||||
bool sharpen;
|
bool sharpen;
|
||||||
bool progressive;
|
bool progressive;
|
||||||
@ -28,7 +29,7 @@ struct resize_baton {
|
|||||||
int compressionLevel;
|
int compressionLevel;
|
||||||
std::string err;
|
std::string err;
|
||||||
|
|
||||||
resize_baton(): buffer_in_len(0), buffer_out_len(0) {}
|
resize_baton(): buffer_in_len(0), buffer_out_len(0), crop(false), max(false), sharpen(false), progressive(false) {}
|
||||||
};
|
};
|
||||||
|
|
||||||
typedef enum {
|
typedef enum {
|
||||||
@ -138,6 +139,14 @@ class ResizeWorker : public NanAsyncWorker {
|
|||||||
double xfactor = static_cast<double>(in->Xsize) / static_cast<double>(baton->width);
|
double xfactor = static_cast<double>(in->Xsize) / static_cast<double>(baton->width);
|
||||||
double yfactor = static_cast<double>(in->Ysize) / static_cast<double>(baton->height);
|
double yfactor = static_cast<double>(in->Ysize) / static_cast<double>(baton->height);
|
||||||
factor = baton->crop ? std::min(xfactor, yfactor) : std::max(xfactor, yfactor);
|
factor = baton->crop ? std::min(xfactor, yfactor) : std::max(xfactor, yfactor);
|
||||||
|
// if max is set, we need to compute the real size of the thumb image
|
||||||
|
if(baton->max) {
|
||||||
|
if(xfactor > yfactor) {
|
||||||
|
baton->height = round(in->Ysize/factor);
|
||||||
|
} else {
|
||||||
|
baton->width = round(in->Xsize/factor);
|
||||||
|
}
|
||||||
|
}
|
||||||
} else if (baton->width > 0) {
|
} else if (baton->width > 0) {
|
||||||
// Fixed width, auto height
|
// Fixed width, auto height
|
||||||
factor = static_cast<double>(in->Xsize) / static_cast<double>(baton->width);
|
factor = static_cast<double>(in->Xsize) / static_cast<double>(baton->width);
|
||||||
@ -226,7 +235,7 @@ class ResizeWorker : public NanAsyncWorker {
|
|||||||
// Crop/embed
|
// Crop/embed
|
||||||
VipsImage *canvased = vips_image_new();
|
VipsImage *canvased = vips_image_new();
|
||||||
if (affined->Xsize != baton->width || affined->Ysize != baton->height) {
|
if (affined->Xsize != baton->width || affined->Ysize != baton->height) {
|
||||||
if (baton->crop) {
|
if (baton->crop || baton->max) {
|
||||||
// Crop
|
// Crop
|
||||||
int width = std::min(affined->Xsize, baton->width);
|
int width = std::min(affined->Xsize, baton->width);
|
||||||
int height = std::min(affined->Ysize, baton->height);
|
int height = std::min(affined->Ysize, baton->height);
|
||||||
@ -351,6 +360,9 @@ NAN_METHOD(resize) {
|
|||||||
} else if (canvas->Equals(NanSymbol("b"))) {
|
} else if (canvas->Equals(NanSymbol("b"))) {
|
||||||
baton->crop = false;
|
baton->crop = false;
|
||||||
baton->extend = VIPS_EXTEND_BLACK;
|
baton->extend = VIPS_EXTEND_BLACK;
|
||||||
|
} else if (canvas->Equals(NanSymbol("m"))) {
|
||||||
|
baton->crop = false;
|
||||||
|
baton->max = true;
|
||||||
}
|
}
|
||||||
baton->sharpen = args[6]->BooleanValue();
|
baton->sharpen = args[6]->BooleanValue();
|
||||||
baton->progressive = args[7]->BooleanValue();
|
baton->progressive = args[7]->BooleanValue();
|
||||||
|
@ -109,6 +109,29 @@ async.series([
|
|||||||
done();
|
done();
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
},
|
||||||
|
// Resize to max width or height considering ratio (landscape)
|
||||||
|
function(done) {
|
||||||
|
sharp(inputJpg).resize(320,320).max().write(outputJpg, function(err) {
|
||||||
|
if (err) throw err;
|
||||||
|
imagemagick.identify(outputJpg, function(err, features) {
|
||||||
|
if (err) throw err;
|
||||||
|
assert.strictEqual(320, features.width);
|
||||||
|
assert.strictEqual(261, features.height);
|
||||||
|
done();
|
||||||
|
});
|
||||||
|
});
|
||||||
|
},
|
||||||
|
// Resize to max width or height considering ratio (portrait)
|
||||||
|
function(done) {
|
||||||
|
sharp(inputTiff).resize(320,320).max().write(outputJpg, function(err) {
|
||||||
|
if (err) throw err;
|
||||||
|
imagemagick.identify(outputJpg, function(err, features) {
|
||||||
|
if (err) throw err;
|
||||||
|
assert.strictEqual(243, features.width);
|
||||||
|
assert.strictEqual(320, features.height);
|
||||||
|
done();
|
||||||
|
});
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
]);
|
]);
|
||||||
|
Loading…
x
Reference in New Issue
Block a user