Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
15 changes: 12 additions & 3 deletions index.js
Original file line number Diff line number Diff line change
Expand Up @@ -43,7 +43,7 @@ var Sharp = function(input) {
width: -1,
height: -1,
canvas: 'crop',
gravity: 0,
gravity: { left: 0.5, top: 0.5 },
angle: 0,
rotateBeforePreExtract: false,
flip: false,
Expand Down Expand Up @@ -132,11 +132,20 @@ Sharp.prototype._write = function(chunk, encoding, callback) {
};

// Crop this part of the resized image (Center/Centre, North, East, South, West)
module.exports.gravity = {'center': 0, 'centre': 0, 'north': 1, 'east': 2, 'south': 3, 'west': 4};
module.exports.gravity = {
'center': { left: 0.5, top: 0.5 },
'centre': { left: 0.5, top: 0.5 },
'north': { left: 0.5, top: 0.0 },
'east': { left: 1.0, top: 0.5 },
'south': { left: 0.5, top: 1.0 },
'west': { left: 0.0, top: 0.5 }
};

Sharp.prototype.crop = function(gravity) {
this.options.canvas = 'crop';
if (typeof gravity === 'number' && !Number.isNaN(gravity) && gravity >= 0 && gravity <= 4) {
if (typeof gravity === 'object' &&
typeof gravity.left === 'number' && !Number.isNaN(gravity.left) && gravity.left >= 0 && gravity.left <= 1 &&
typeof gravity.top === 'number' && !Number.isNaN(gravity.top) && gravity.top >= 0 && gravity.top <= 1) {
this.options.gravity = gravity;
} else {
throw new Error('Unsupported crop gravity ' + gravity);
Expand Down
38 changes: 12 additions & 26 deletions src/resize.cc
Original file line number Diff line number Diff line change
Expand Up @@ -73,7 +73,8 @@ struct ResizeBaton {
int width;
int height;
Canvas canvas;
int gravity;
double gravityLeft;
double gravityTop;
std::string interpolator;
double background[4];
bool flatten;
Expand Down Expand Up @@ -111,7 +112,8 @@ struct ResizeBaton {
topOffsetPre(-1),
topOffsetPost(-1),
canvas(Canvas::CROP),
gravity(0),
gravityLeft(0.5),
gravityTop(0.5),
flatten(false),
blurSigma(0.0),
sharpenRadius(0),
Expand Down Expand Up @@ -619,7 +621,7 @@ class ResizeWorker : public NanAsyncWorker {
// Crop/max/min
int left;
int top;
std::tie(left, top) = CalculateCrop(image->Xsize, image->Ysize, baton->width, baton->height, baton->gravity);
std::tie(left, top) = CalculateCrop(image->Xsize, image->Ysize, baton->width, baton->height, baton->gravityLeft, baton->gravityTop);
int width = std::min(image->Xsize, baton->width);
int height = std::min(image->Ysize, baton->height);
VipsImage *extracted;
Expand Down Expand Up @@ -1054,28 +1056,10 @@ class ResizeWorker : public NanAsyncWorker {
within the input image, applying the given gravity.
*/
std::tuple<int, int>
CalculateCrop(int const inWidth, int const inHeight, int const outWidth, int const outHeight, int const gravity) {
int left = 0;
int top = 0;
switch (gravity) {
case 1: // North
left = (inWidth - outWidth + 1) / 2;
break;
case 2: // East
left = inWidth - outWidth;
top = (inHeight - outHeight + 1) / 2;
break;
case 3: // South
left = (inWidth - outWidth + 1) / 2;
top = inHeight - outHeight;
break;
case 4: // West
top = (inHeight - outHeight + 1) / 2;
break;
default: // Centre
left = (inWidth - outWidth + 1) / 2;
top = (inHeight - outHeight + 1) / 2;
}
CalculateCrop(int const inWidth, int const inHeight, int const outWidth, int const outHeight,
double const gravityLeft, double const gravityTop) {
int left = (inWidth - outWidth) * gravityLeft;
int top = (inHeight - outHeight) * gravityTop;
return std::make_tuple(left, top);
}

Expand Down Expand Up @@ -1177,7 +1161,9 @@ NAN_METHOD(resize) {
}
// Resize options
baton->withoutEnlargement = options->Get(NanNew<String>("withoutEnlargement"))->BooleanValue();
baton->gravity = options->Get(NanNew<String>("gravity"))->Int32Value();
Local<Object> gravity = options->Get(NanNew<String>("gravity"))->ToObject();
baton->gravityLeft = gravity->Get(NanNew<String>("left"))->NumberValue();
baton->gravityTop = gravity->Get(NanNew<String>("top"))->NumberValue();
baton->interpolator = *String::Utf8Value(options->Get(NanNew<String>("interpolator"))->ToString());
// Operators
baton->flatten = options->Get(NanNew<String>("flatten"))->BooleanValue();
Expand Down