lovell / lovell/sharp

Calculating "fit over" dimensions (fit on either axis)

Open
#3,131 5 comments 0 reactions 0 assignees View on GitHub

Nobody has claimed this yet.

enhancement
Dominant language
JavaScript
Stars
32.7k
Forks
1.4k
Avg merge
1d 14h
Merged PRs (30d)
5

Description

Feature 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?)

Contributor guide

Open the contributing guide

First steps

  1. Read the whole issue, then the project's contributing guide.
  2. Comment on the issue to say you are picking it up — it saves two people doing the same work.
  3. Fork the repository and make your change on a branch.
  4. Open a pull request that references the issue number.

Research direction

Start by reviewing the existing resize options API and the metadata entry point, since the request depends on both. Determine whether the behavior belongs in the API or documentation, resolve how it interacts with enlargement and reduction constraints, and define the expected result before implementation.

Written by the indexing model from the issue text.

Assessment

Tech stack
javascript, nodejs
Domain
api, backend
Issue type
Feature
Difficulty
5/5
Estimated time
Over a week
Activity status
Stale
Clarity
Needs clarification
Newbie friendliness
32/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.