Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add the ability to pad an image #128

Closed
blowsie opened this issue Nov 27, 2014 · 29 comments
Closed

Add the ability to pad an image #128

blowsie opened this issue Nov 27, 2014 · 29 comments
Milestone

Comments

@blowsie
Copy link

blowsie commented Nov 27, 2014

It would be great to see something much like the implementation here
https://github.com/EyalAr/lwip#user-content-pad

@lovell
Copy link
Owner

lovell commented Nov 27, 2014

Would you be using this in a web context, i.e. producing an image that is part of an HTML document? If so, could CSS provide what you're looking for?

@blowsie
Copy link
Author

blowsie commented Nov 27, 2014

Not quite, you could potentially read the pixel color from the image, and pad the image with this color.
There are of course other use cases.

@lovell
Copy link
Owner

lovell commented Nov 27, 2014

"you could potentially read the pixel color from the image"

Which pixel(s) does this refer to? Would a method that returned the dominant/average colour of an image help?

From what I understand of the lwip docs, its pad method defaults to transparent if no colour is provided. Is this the behaviour you need?

@blowsie
Copy link
Author

blowsie commented Nov 27, 2014

Which pixel(s) does this refer to? Would a method that returned the dominant/average colour of an image help?

Ultimately I'm just looking for the ability to pad an image, in my case where I may want to specify a color I may opt to use another library to retreive / calculate the color

From what I understand of the lwip docs, its pad method defaults to transparent if no colour is provided. Is this the behaviour you need?

That would be great

@bennlich
Copy link

bennlich commented Apr 7, 2015

I am also in need of the pad functionality. I'd like to make square image tiles from rectangular images, adding transparent pixels for padding where necessary (i.e. to pad the shorter of the two dimensions). Is there a work-around with the current API?

@lovell
Copy link
Owner

lovell commented Apr 8, 2015

@bennlich you should be able to to do with the existing API via a combination of the embed and background methods. https://github.com/lovell/sharp/blob/master/test/unit/embed.js#L32-L37 provides an example of this.

@bennlich
Copy link

bennlich commented Apr 8, 2015

Ah! Awesome, thanks a bunch for the quick reply.

@bennlich
Copy link

bennlich commented Apr 8, 2015

Is there a way to specify where the image is embedded in the larger image (bottom left, top right, etc.)? Kind of like a gravity option for embed?

@lovell
Copy link
Owner

lovell commented Apr 8, 2015

@bennlich Reusing gravity to apply to the embed operation also would make a good addition, thanks for the idea.

@blowsie Does any of what @bennlich and I are discussing meet your needs, or should I move this new suggestion to a separate task?

@blowsie
Copy link
Author

blowsie commented Apr 9, 2015

I'm not sure without testing, which I don't have time to do right now.
I personally would love to see .pad(10,10,10,10) or similar as some sort of mixin rather than combining various other functions.

The embed function however does look useful for one of my use cases, which matches @bennlich s requirements of fitting rectangles in squares.

@mikemliu
Copy link

I'm trying to achieve something similar, where I have a "zoom" or "crop" feature that lets the user specify how to process their image.

To embed a smaller image on a larger background, resorting to below. Wondering if it can be reduced to 1 pipeline instead of 2?

So, starting with a 50x50 image, i want to center it in a 256x256 background:

sharp(in)
.resize(50, 256)
.embed()
.pipe(sharp().resize(256, 256).embed())
.pipe(out)

The first resize essentially centers the image vertically on a 50x256 background, then a second pass centers it in the 256x256 background. Inefficient, but gets the job done. hoping for better alternative...

ideally works like drawing on a canvas where we specify source rectangle on the image and destination rectangle on the background.

@blowsie
Copy link
Author

blowsie commented May 7, 2015

So after testing, using embed in combination with background; this caters for @bennlich s use case, however it doesnt let you add some padding / whitespace to the image, as desired

@bennlich
Copy link

bennlich commented May 7, 2015

Because of the lack of something like a "centered" gravity option?

On Thu, May 7, 2015 at 7:57 AM, Sam Blowes [email protected] wrote:

So after testing, using embed in combination with background caters for
@bennlich https://github.com/bennlich s use case, however it doesnt let
you add some padding / whitespace to the image, as desired


Reply to this email directly or view it on GitHub
#128 (comment).

@blowsie
Copy link
Author

blowsie commented May 8, 2015

Well, as far as I know, you can only resize, and not extend / pad. Perhaps you can do this with embed somehow? I'm not sure

@mikemliu
Copy link

mikemliu commented May 8, 2015

Gravity is not enough control to embed an image on a specific area of a background. For example, I want to embed a 50x50 image on the lower left corner of a 256x256 background, or any other specific position on the background. Imagine an image cropper use case where you allow the user to place an avatar in a region.

@masimplo
Copy link

Would also love to see a padding function. My use case involves a square avatar image that is to be overlaid with a square having a round transparent area in the center (thus creating the illusion of a round avatar). Problem is since source and dest images in overlay function need to be the same size I am losing part of the original image and would love to resize it down a few pixels and adding the same as padding to accommodate for overlay function's requirement.

@lovell
Copy link
Owner

lovell commented Oct 14, 2015

@masimakopoulos The existing embed option may provide some of what you're looking for.

Assuming you have a transparent overlay image of 300x300px, the following will create a 300x300 white image with input.jpg embedded then round.png overlaid.

sharp('input.jpg')
  .resize(300, 300)
  .background({r: 255, g: 255, b: 255})
  .embed()
  .overlayWith('round.png')
  .toFile( ... )

@masimplo
Copy link

@lovell thanks for the response. I tried the above but it does not pad the image it just makes everything the size of the overlay (stretches the target image). Not sure if it make as difference but the target image ('input.jpg') is a stream passed through some other sharp manipulations.

Here is what I am doing:

    getAvatar() // Get an image stream from a remote source
   .pipe(sharp().resize(size, size).withoutEnlargement()) //resize the retrieved image to a predefined size
   // later on (optionally) trying to add overlay with padding
   .pipe(sharp()
        .png() //need to convert to png first, otherwise result looks really weird from jpg target
        .resize(54, 54) //image was already 54x54 by previous manipulation
        .background({r: 255, g: 255, b: 255})
        .embed()
        .overlayWith('lib/assets/overlay_s54.png'));  // overlay is 54x54px

Note the above is a simplification of my process. The first resize can be done without an overlay being added, thus the duplication in logic in this example.

I am also using the latest version 0.11.3

@lovell
Copy link
Owner

lovell commented Oct 15, 2015

"stretches the target image"

The only time stretching should occur is with the use of ignoreAspectRatio - perhaps we've unearthed a bug here - let me investigate.

@masimplo
Copy link

No, what I meant was it enlarged the target image, instead of adding padding to it (both axis, so not ignoring aspect ratio). I apologize for the confusion.

@lovell
Copy link
Owner

lovell commented Oct 16, 2015

@masimakopoulos No worries, thanks for confirming 😌

@lovell
Copy link
Owner

lovell commented Mar 1, 2016

I think extend is the right name for this behaviour.

An example of this, when used in conjunction with existing resize and background methods, might be:

sharp(input)
  .resize(180)
  .background({r: 100, g: 0, b: 0})
  .extend({top: 10, left: 10, bottom: 20, right: 10})
  .toBuffer( ... )

The resultant image would be 200 pixels wide (by whatever high). It would have a dark red border of 10 pixels to the top and sides and 20 pixels to the bottom.

@lovell lovell added this to the v0.14.0 milestone Mar 1, 2016
@lovell
Copy link
Owner

lovell commented Mar 3, 2016

Commit f950294 on the needle branch adds the new extend feature, which will be in v0.14.0.

@masimplo
Copy link

masimplo commented Mar 3, 2016

Great news! Looking forward to this release.

@blowsie
Copy link
Author

blowsie commented Mar 7, 2016

++ Many thanks!

@lovell
Copy link
Owner

lovell commented Apr 2, 2016

v0.14.0 now available via npm, thanks again for all the comments and help here.

@lovell lovell closed this as completed Apr 2, 2016
@srameshr
Copy link

Thanks for this. You are a saviour!

@simeyla
Copy link

simeyla commented Aug 13, 2018

Why do I always read these threads from start to finish!? Because sometimes they get exciting, like little mini stories putting me on the edge of my seat. Happy to see this had a good ending :-) I needed this functionality to be able to put a css rounded border (to make the image a circle) so needed to extend it.

However @lovell I think you have this in the wrong place in the documentation. It is currently under image operations 'http://sharp.pixelplumbing.com/en/stable/api-operation/#extend'.

It would be really helpful to add this under resizing images where I think people are much more likely to be looking. http://sharp.pixelplumbing.com/en/stable/api-resize/ Same maybe goes for trim.

@lovell
Copy link
Owner

lovell commented Aug 13, 2018

@simeyla I've added a note about this to #1135

Repository owner locked and limited conversation to collaborators Aug 13, 2018
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Projects
None yet
Development

No branches or pull requests

7 participants