Skip to content

Commit

Permalink
Add gravity support to embed feature (lovell#1038)
Browse files Browse the repository at this point in the history
  • Loading branch information
AzureByte authored and lovell committed Dec 12, 2017
1 parent 1d7a0ea commit 927b777
Show file tree
Hide file tree
Showing 28 changed files with 426 additions and 7 deletions.
1 change: 1 addition & 0 deletions lib/constructor.js
Original file line number Diff line number Diff line change
Expand Up @@ -136,6 +136,7 @@ const Sharp = function (input, options) {
height: -1,
canvas: 'crop',
crop: 0,
embed: 0,
useExifOrientation: false,
angle: 0,
rotateBeforePreExtract: false,
Expand Down
19 changes: 17 additions & 2 deletions lib/resize.js
Original file line number Diff line number Diff line change
Expand Up @@ -179,11 +179,26 @@ function crop (crop) {
* // outputBuffer contains WebP image data of a 200 pixels wide and 300 pixels high
* // containing a scaled version, embedded on a transparent canvas, of input.gif
* });
*
* @param {String} [embed='centre'] - A member of `sharp.gravity` to embed to an edge/corner.
* @returns {Sharp}
* @throws {Error} Invalid parameters
*/
function embed () {
function embed (embed) {
this.options.canvas = 'embed';

if (!is.defined(embed)) {
// Default
this.options.embed = gravity.center;
} else if (is.integer(embed) && is.inRange(embed, 0, 8)) {
// Gravity (numeric)
this.options.embed = embed;
} else if (is.string(embed) && is.integer(gravity[embed])) {
// Gravity (string)
this.options.embed = gravity[embed];
} else {
throw is.invalidParameterError('embed', 'valid embed id/name', embed);
}

return this;
}

Expand Down
4 changes: 3 additions & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -40,7 +40,8 @@
"Nicolas Coden <[email protected]>",
"Matt Parrish <[email protected]>",
"Matthew McEachen <[email protected]>",
"Jarda Kotěšovec <[email protected]>"
"Jarda Kotěšovec <[email protected]>",
"Kenric D'Souza <[email protected]>"
],
"scripts": {
"clean": "rm -rf node_modules/ build/ vendor/ coverage/ test/fixtures/output.*",
Expand All @@ -66,6 +67,7 @@
"resize",
"thumbnail",
"crop",
"embed",
"libvips",
"vips"
],
Expand Down
57 changes: 56 additions & 1 deletion src/common.cc
Original file line number Diff line number Diff line change
Expand Up @@ -409,7 +409,62 @@ namespace sharp {

/*
Calculate the (left, top) coordinates of the output image
within the input image, applying the given gravity.
within the input image, applying the given gravity during an embed.
@Azurebyte: We are basically swapping the inWidth and outWidth, inHeight and outHeight from the CalculateCrop function.
*/
std::tuple<int, int> CalculateEmbedPosition(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 = (outWidth - inWidth) / 2;
break;
case 2:
// East
left = outWidth - inWidth;
top = (outHeight - inHeight) / 2;
break;
case 3:
// South
left = (outWidth - inWidth) / 2;
top = outHeight - inHeight;
break;
case 4:
// West
top = (outHeight - inHeight) / 2;
break;
case 5:
// Northeast
left = outWidth - inWidth;
break;
case 6:
// Southeast
left = outWidth - inWidth;
top = outHeight - inHeight;
break;
case 7:
// Southwest
top = outHeight - inHeight;
break;
case 8:
// Northwest
// Which is the default is 0,0 so we do not assign anything here.
break;
default:
// Centre
left = (outWidth - inWidth) / 2;
top = (outHeight - inHeight) / 2;
}
return std::make_tuple(left, top);
}

/*
Calculate the (left, top) coordinates of the output image
within the input image, applying the given gravity during a crop.
*/
std::tuple<int, int> CalculateCrop(int const inWidth, int const inHeight,
int const outWidth, int const outHeight, int const gravity) {
Expand Down
7 changes: 7 additions & 0 deletions src/common.h
Original file line number Diff line number Diff line change
Expand Up @@ -206,6 +206,13 @@ namespace sharp {
*/
std::string VipsWarningPop();

/*
Calculate the (left, top) coordinates of the output image
within the input image, applying the given gravity during an embed.
*/
std::tuple<int, int> CalculateEmbedPosition(int const inWidth, int const inHeight,
int const outWidth, int const outHeight, int const gravity);

/*
Calculate the (left, top) coordinates of the output image
within the input image, applying the given gravity.
Expand Down
20 changes: 17 additions & 3 deletions src/pipeline.cc
Original file line number Diff line number Diff line change
Expand Up @@ -446,12 +446,25 @@ class PipelineWorker : public Nan::AsyncWorker {
image = image.bandjoin(
VImage::new_matrix(image.width(), image.height()).new_from_image(255 * multiplier));
}

// Embed
int left = static_cast<int>(round((baton->width - image.width()) / 2));
int top = static_cast<int>(round((baton->height - image.height()) / 2));
image = image.embed(left, top, baton->width, baton->height, VImage::option()

// Calculate where to position the embeded image if gravity specified, else center.
int left;
int top;

left = static_cast<int>(round((baton->width - image.width()) / 2));
top = static_cast<int>(round((baton->height - image.height()) / 2));

int width = std::max(image.width(), baton->width);
int height = std::max(image.height(), baton->height);
std::tie(left, top) = sharp::CalculateEmbedPosition(
image.width(), image.height(), baton->width, baton->height, baton->embed);

image = image.embed(left, top, width, height, VImage::option()
->set("extend", VIPS_EXTEND_BACKGROUND)
->set("background", background));

} else if (baton->canvas != Canvas::IGNORE_ASPECT) {
// Crop/max/min
if (baton->crop < 9) {
Expand Down Expand Up @@ -1141,6 +1154,7 @@ NAN_METHOD(pipeline) {
// Resize options
baton->withoutEnlargement = AttrTo<bool>(options, "withoutEnlargement");
baton->crop = AttrTo<int32_t>(options, "crop");
baton->embed = AttrTo<int32_t>(options, "embed");
baton->kernel = AttrAsStr(options, "kernel");
baton->fastShrinkOnLoad = AttrTo<bool>(options, "fastShrinkOnLoad");
// Join Channel Options
Expand Down
2 changes: 2 additions & 0 deletions src/pipeline.h
Original file line number Diff line number Diff line change
Expand Up @@ -62,6 +62,7 @@ struct PipelineBaton {
int channels;
Canvas canvas;
int crop;
int embed;
bool hasCropOffset;
int cropOffsetLeft;
int cropOffsetTop;
Expand Down Expand Up @@ -145,6 +146,7 @@ struct PipelineBaton {
channels(0),
canvas(Canvas::CROP),
crop(0),
embed(0),
hasCropOffset(false),
cropOffsetLeft(0),
cropOffsetTop(0),
Expand Down
Binary file added test/fixtures/embedgravitybird.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added test/fixtures/expected/embedgravitybird/1-nw.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added test/fixtures/expected/embedgravitybird/2-n.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added test/fixtures/expected/embedgravitybird/3-ne.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added test/fixtures/expected/embedgravitybird/4-e.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added test/fixtures/expected/embedgravitybird/5-se.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added test/fixtures/expected/embedgravitybird/6-s.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added test/fixtures/expected/embedgravitybird/7-sw.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added test/fixtures/expected/embedgravitybird/8-w.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added test/fixtures/expected/embedgravitybird/9-c.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
1 change: 1 addition & 0 deletions test/fixtures/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -85,6 +85,7 @@ module.exports = {
inputPngBooleanNoAlpha: getPath('bandbool.png'),
inputPngTestJoinChannel: getPath('testJoinChannel.png'),
inputPngTruncated: getPath('truncated.png'), // gm convert 2569067123_aca715a2ee_o.jpg -resize 320x240 saw.png ; head -c 10000 saw.png > truncated.png
inputPngEmbed: getPath('embedgravitybird.png'), // Released to sharp under a CC BY 4.0

inputWebP: getPath('4.webp'), // http://www.gstatic.com/webp/gallery/4.webp
inputWebPWithTransparency: getPath('5_webp_a.webp'), // http://www.gstatic.com/webp/gallery3/5_webp_a.webp
Expand Down
Loading

0 comments on commit 927b777

Please sign in to comment.