image icon indicating copy to clipboard operation
image copied to clipboard

Shortcut for resize() with upsize/aspect ratio constraints

Open barryvdh opened this issue 11 years ago • 30 comments

Maybe it's just me, but most of the times I want to resize an image to max width/height, but keep the aspect ratio (because that ruins the photo) and no upsize (because that only leads to ugly pixelated pics), and don't want to crop because that cuts of important parts. So I end up adding the constraints all the time:

$image->resize(800, 800 , function ($constraint) {
        $constraint->aspectRatio();
        $constraint->upsize();
    }

Is it possible to make this a dedicated function, or can I define my own Macro's or something?

barryvdh avatar Sep 12 '14 12:09 barryvdh

You can use widen(), heighten() or fit().

http://image.intervention.io/api/widen http://image.intervention.io/api/heighten http://image.intervention.io/api/fit

olivervogel avatar Sep 12 '14 12:09 olivervogel

Yes but fit() crops the image right? So I'd just use $image->widen(800)->heighten(800). But than I still need to add the upsize constraints to both calls?

barryvdh avatar Sep 12 '14 12:09 barryvdh

Yes, fit() crops, but in an intelligent way.

To prevent upsizing you have to do this:

$callback = function ($constraint) { $constraint->upsize(); };
$image->widen(800, $callback)->heighten(800, $callback)

It's also possible to combine calls into filters and just run code like this:

$image->filter(new CustomResize(800, 800));

I'm thinking at the moment about a global configuration, where you not only can set driver, but also global defaults like output format, encoding quality etc. Maybe I can add default settings for constraints.

olivervogel avatar Sep 12 '14 12:09 olivervogel

Would be cool. I can't really imagine a situation (for me) where I'd want images to be upsized or not keeping aspect ration.

barryvdh avatar Sep 12 '14 13:09 barryvdh

I thought about this and think, that my "global default config" idea might bring more confusion than logic.

But I agree, the resize() method is quite verbose and it might be a good idea to have a shortcut for resizing with keeping aspect-ratio and prevent upsizing.

Any ideas on naming this shortcut?

olivervogel avatar Sep 14 '14 11:09 olivervogel

Scale or downscale perhaps? Or perhaps scale does upsize and downscale doesn't. But I'm not sure, not really into photo editing terms.. Op 14 sep. 2014 13:59 schreef "Oliver Vogel" [email protected]:

I thought about this and think, that my "global default config" idea might bring more confusion than logic.

But I agree, the resize() method is quite verbose and it might be a good idea to have a shortcut for resizing with keeping aspect-ratio and prevent upsizing.

Any ideas on naming this shortcut?

— Reply to this email directly or view it on GitHub https://github.com/Intervention/image/issues/227#issuecomment-55523369.

barryvdh avatar Sep 14 '14 12:09 barryvdh

I thought about scale too.

olivervogel avatar Sep 14 '14 12:09 olivervogel

Hi,

This should really be called contain imho to keep with css bg-size terms http://www.w3schools.com/cssref/css3_pr_background-size.asp

I think $image->widen(800, $callback)->heighten(800, $callback) is not optimal, for one, it may resize the image twice needlessly losing precious details and resources.

for now I did something like this:

public static function contain(&$image, $maxWidth, $maxHeight)
{
  $currentWidth = $image->width(); $currentHeight = $image->height();
  if (currentWidth > maxdWidth || currentHeight > maxHeight)
  {
    $ratioX = currentWidth / maxdWidth;
    $ratioY = currentHeight / maxHeight;
    if (ratioX > ratioY) $image->widen($maxWidth);
    else $image->heighten($maxHeight);
  }
}

arthur-white avatar Oct 12 '14 16:10 arthur-white

@arthur-white isn't that similar to my example?

$image->resize($maxWidth, $maxHeight, function ($constraint) {
    $constraint->aspectRatio();
    $constraint->upsize();
}

I'm also fine with contain, or scale or whatever you like ;)

barryvdh avatar Oct 14 '14 11:10 barryvdh

I don't really like contain. And in terms of CSS it is possible to get an upsized image, which is not wanted here.

I think a good way would be, to make the upsize prevention set by default. Because in almost every situation upsizing is not wanted. But this step would break the whole constraint naming concept and would be not backward compatible. So I guess this is not an option.

olivervogel avatar Oct 16 '14 17:10 olivervogel

Okay, so scale it is? Do you need a PR or do you have in mind what the best way to do this is?

barryvdh avatar Nov 10 '14 15:11 barryvdh

Sorry, I can't decide for a good and distinct name.

olivervogel avatar Nov 10 '14 16:11 olivervogel

Okay new suggestion, use a string to define a shortcut for some callbacks. So if the third param is a string, use a predefined callback. Something similar to these fit options: http://glide.thephpleague.com/api/size/

$image->fit(800, 800, 'contain');
$image->fit(800, 800, 'stretch');
$image->fit(800, 800, 'crop');
$image->fit(800, 800, 'max');

barryvdh avatar Jan 07 '15 16:01 barryvdh

Following the naming of Glide (which is based on intervention/image), the stretch is what currently is resize. contain is the resizing + aspect ratio and max is what I wanted to do in the OP, resize + keep ratio + don't upscale. crop is just the regular fit().

So following that, I could probably see the usage of 2 new functions:

$image->max($width, $height);
$image->contain($width, $height);

Imho both max and contain are more common then the stretch/resize, because that gives you distorted images..

And about the current fit, it probably doesn't make a lot of sense to add constraints because you usually want an exact fit (hence the name), and the 4th param is more useful sometimes. But I guess the interface can't be changed in the 2.x version.

/cc @reinink because he implemented all this :)

barryvdh avatar Jan 08 '15 13:01 barryvdh

Thanks for including me @barryvdh. My naming for the fit feature may not be perfect, but as is always the case with naming, it's hard. I based it on what I've seen done in other libraries, with some tweaks of my own.

I liked contain instead of resize because all these functions are doing a resize, so why should this one be called that? In my mind I saw the image being contained to the target dimensions, but with nothing else happening (distorting or cropping). I've also seen this called clip, but for me that didn't immediately conjure up a visual of what was happening.

As for stretch, that was also something I came up with. Stretch gives the idea that the image is being distorted. I even considered distort as an option, which I don't think would have been terrible. I went with stretch because it had more of a sizing connotation to it. I've also seen scale used for this.

The max and crop settings I've seen used elsewhere, and both made sense to me right away.

reinink avatar Jan 08 '15 14:01 reinink

While I'm here, I'd like to thank you @olivervogel. This library is really awesome, and works in a very straight forward and expected way. It really took all of the hard work out of creating Glide. Thanks! :clap:

reinink avatar Jan 08 '15 14:01 reinink

Thanks for your suggestions guys. I like the thought of having distinct and easy methods for the three tasks:

  • resize
  • resize + aspect-ratio
  • resize + aspect-ratio + no-upsize

I'm currently working on the next release of Intervention Image. This next version will introduce some minor but backward-incompatible API changes. This may be a chance to rename resize() and add new methods.

Currently these renamings are my favorites.

  • resize -> stretch
  • resize + aspect-ratio -> resize
  • resize + aspect-ratio + no-upscale -> maybe max but I'm not 100% happy

olivervogel avatar Jan 08 '15 15:01 olivervogel

Could also be something like shrink to imply it only shrinks, not enlarges.

This is an alternative naming: https://github.com/Gregwar/Image#basic-handling Which makes not-upsizing the default resize and has scaleResize to allow upsizing, forceResize instead of stretch (and cropResize instead of fit)

I'm just happy as the max equivalent becomes available under 1 easy call, I'll live with whatever name is chosen :)

barryvdh avatar Jan 09 '15 08:01 barryvdh

@barryvdh I totally agree with the point you make in the first post. Would love to not have to do the closure for upsize and ratio.

juukie avatar Feb 08 '15 18:02 juukie

@barryvdh your first solution doesnt work for me.. it takes the first param (width) only as a constraint. Is there any method to fit width and height, keeping the ratio, without cropping?

capsule5 avatar Jun 08 '15 11:06 capsule5

I'm just new to this library, and is looking for exactly what @barryvdh is asking for. Is there any update to this issue since it was created, though its still open?

I can see there is also the resizeCanvas - it kinda sounds like what I want to do, but having a hard time figurering it out from the documentation.

Thanks for otherwise what seems to be an awesome library!

rasmuscnielsen avatar Sep 06 '15 08:09 rasmuscnielsen

Any updates on this? Still not 100% happy about max()? Does this need to be on the nextVersion? Adding an alias to an existing function should break BC, just a minor version bump.

barryvdh avatar Dec 01 '15 09:12 barryvdh

Any news on this issue? A short alias would be really nice for this.

fabianpimminger avatar Feb 10 '16 10:02 fabianpimminger

contain should be something like this:

function($x, $y, $bgfillcolor) {
return $image->resize($x, $y, function($constraint) {
            $constraint->aspectRatio();
            $constraint->upsize();
        })->resizeCanvas($x, $y, 'center', false, $bgfillcolor);
}

riyuk avatar Feb 11 '16 17:02 riyuk

Thanks for all dalaos!

njwangchuan avatar Apr 05 '16 08:04 njwangchuan

Seems this was discussed for 2 years and then the discussion stopped. When will the scale option be added?

jasperf avatar Jul 31 '19 12:07 jasperf

@olivervogel what about the word fill?

bilogic avatar Aug 28 '19 15:08 bilogic

@olivervogel or pad?

bilogic avatar Aug 28 '19 17:08 bilogic

Is there an update on this? Whats the preferred way now to scale while keeping respect aspect ratio?

renepardon avatar Apr 21 '21 05:04 renepardon

I totally agree with @barryvdh. I havent run into a scenario yet where I would like to upscale without aspect ratio. I'm using this everywhere.

$image->resize($maxWidth, $maxHeight, function ($constraint) {
    $constraint->aspectRatio();
    $constraint->upsize();
}

And for the naming, maybe you can find some inspiration here: https://developer.mozilla.org/en-US/docs/Web/CSS/object-fit

jeroenstoker avatar Aug 30 '22 19:08 jeroenstoker