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

Have crop not increase the size of the input image if it is smaller than the output size (or have a new fit option that does this) #293

Open
PatrikCo opened this issue Nov 10, 2020 · 1 comment

Comments

@PatrikCo
Copy link

Love the project!

I'm using it inside a CMS, so i cannot control what the input images are. Most of them are bigger than the output size, so Glide and its crop option do exactly what is needed.

But once in a while an image gets uploaded by the users that is actually a bit smaller than the output size. The glide crop feature then proceeds to enlarge the image, therefore transferring more pixels to the customer than were originally there.

I think this step of increasing the resolution should be done by the visitors browser instead (we specified the image resolution in the CSS as well, so the browser will do it). By not unnecessarily increasing the resolution we would also save bandwidth.

So what I wish is that crop in this case crops the image to the target aspect ratio, and not unnecessarily increases the resolution, and deliver that image.

Or if you wish to keep the crop behaviour the same, I wish that there is a new fit option, probably called crop-max.

Many thanks,
Patrik

@mlazze
Copy link
Contributor

mlazze commented Nov 12, 2020

Facing the same problem. We also require that when we need a bigger image, void space should be filled with white.

So if i say crop to 400x400 the resulting image will be exactly 400x400, without upscaling, cropping unneeded parts and adding white background if needed.

Here's my cheapish solution, supporting crop-top-left and similar crops too. crop-x-y is not supported.

Instead of using the default League\Glide\Manipulators\Size manipulator, i'm using this:

use Intervention\Image\Image;
use League\Glide\Manipulators\Size;

class CropAddsBackgroundIfNeededSize extends Size {
    /**
     * This crops as League\Glide\Manipulators\Size if no upscale needed, but instead of upscaling it adds white space
     * @inheritDoc
     */
    public function runCropResize(Image $image, $width, $height) {
        [$resize_width, $resize_height] = $this->resolveCropResizeDimensions($image, $width, $height);

        $zoom = $this->getCrop()[2];

        $image->resize(
            $resize_width * $zoom,
            $resize_height * $zoom,
            function ($constraint) {
                $constraint->aspectRatio();
                $constraint->upsize();
            }
        );

        $resultIsWider  = $width > $image->width();
        $resultIsTaller = $height > $image->height();
        if (! $resultIsWider && ! $resultIsTaller) {
            [$offset_x, $offset_y] = $this->resolveCropOffset($image, $width, $height);

            return $image->crop($width, $height, $offset_x, $offset_y);
        }
        if ($resultIsWider && $resultIsTaller) {
            $anchor = 'center';
        } elseif ($resultIsWider) {
            $cropMethods = [
                'crop-top-left'     => 'top',
                'crop-top'          => 'top',
                'crop-top-right'    => 'top',
                'crop-left'         => 'center',
                'crop-center'       => 'center',
                'crop-right'        => 'center',
                'crop-bottom-left'  => 'bottom',
                'crop-bottom'       => 'bottom',
                'crop-bottom-right' => 'bottom',
            ];
            $anchor      = $cropMethods[$this->fit] ?? 'center';
        } else {
            $cropMethods = [
                'crop-top-left'     => 'left',
                'crop-top'          => 'center',
                'crop-top-right'    => 'right',
                'crop-left'         => 'left',
                'crop-center'       => 'center',
                'crop-right'        => 'right',
                'crop-bottom-left'  => 'left',
                'crop-bottom'       => 'center',
                'crop-bottom-right' => 'right',
            ];
            $anchor      = $cropMethods[$this->fit] ?? 'center';
        }

        return $image->resizeCanvas($width, $height, $anchor);
    }
}

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants