Calculating "fit over" dimensions (fit on either axis)
See original GitHub issueFeature request
What are you trying to achieve?
Calculate “fit over” dimensions.
This is the term that I recall some image programs using in the past - I can’t really explain why it’s named that way, but basically this means:
Constrain the width and height to a given “size” on either axis.
So, if the image is wide, constrain the width - if it’s tall, constrain the height.
This is useful when you want to constrain the overall number of pixels - for example, assuming you have mixed content with both portrait and landscape images, let’s say you want to produce full-screen images to use on phones and tablets, where the display can be rotated.
When you searched for similar feature requests, what did you find that might be related?
Nuthin’.
What would you expect the API to look like?
I don’t know if this is a good fit for the existing resize
options API - having another option could get confusing, as this likely won’t “play nice” or make sense in combination with some of the other existing options.
What alternatives have you considered?
The better solution might be another documentation entry.
Here’s what I came up with:
function fitTo(size, width, height, { withoutEnlargement, withoutReduction } = {}) {
let ratio = width > height
? size / width
: size / height;
if (withoutEnlargement) {
ratio = Math.min(ratio, 1);
}
if (withoutReduction) {
ratio = Math.max(ratio, 1);
}
return {
width: Math.round(width * ratio),
height: Math.round(height * ratio),
ratio
}
}
This will constrain the given width
or height
to a given size
, while preserving proportions.
I added options to constrain the resulting width
and height
to ratios either withoutEnlargement
or withoutReduction
- these are identical to how the resize
options work.
I’m not certain if these options are necessary - I mean, you could just pass the unconstrained dimensions and the same options to resize
after, so maybe this is enough:
function fitTo(size, width, height) {
let ratio = width > height
? size / width
: size / height;
return {
width: Math.round(width * ratio),
height: Math.round(height * ratio),
ratio
}
}
Alternatively, maybe we could add a size
option to resize
, although as said, this might get confusing, since it would have to ignore width
and height
if size
is specified.
This function requires you first obtain the width
and height
from metadata
, which could be an argument for actually including this feature in the API somehow - if we just add an example to the documentation, it’s hard to say if it belongs in documentation for resize
or metadata
. (If you’re trying to resize an image to fit, you’re most likely looking at the documentation for resize
- but the function itself requires information from metadata
, so which does it relate more to?)
Issue Analytics
- State:
- Created 2 years ago
- Comments:5 (2 by maintainers)
Ok this was definitely more involved than I anticipated but here it is:
This is a port from pipeline.cc only
noPreshrink
must be manually specified which can be determined as followsAlthough I’m not sure if this can be known from the output of
.metadata()
maybespace: 'srgb'
andhasProfile: false
is enough? if not it would be good to add missing stuff to metadata output.One thing which didn’t work was
fit: 'fill'
there I had to swap the axes at the end ofresolveShrink
.@ssendev Great job, thanks a lot. I have been looking for a solution for several days and already thought of digging into the source codes of C. But you did it before me and saved a lot of time. Thanks again.
I see so many requests from people to make this functionality part of the library, I don’t understand why it’s being ignored.