Ticket #560 (assigned Bug)

Opened 6 months ago

Last modified 2 months ago

Extending & correcting logic on Image library

Reported by: jonathangordon Owned by: Shadowhand
Priority: minor Milestone: 2.2
Component: Libraries:Image Version: SVN HEAD
Keywords: image, crop, resize, aspect ratio, logic Cc:

Description

Okay, let's assume someone wants to cut a full size image down to fit into a cropped box size of 300x100 pixels:

$image->resize(300, 100)->crop(300, 100)

This won't work.

Well, it could, but only if the aspect ratio is respective of the desired crop aspect ratio. Instead, what will (almost always) happen is the image will fall inside of the box size required, which in this case is 300x100, and the resulting crop will be smaller on one side, in this case; the width, meaning our final cropped image size will end up being 133x100 for a standard 4:3 image, and even worse for tall images. This just won't do.

To get the desired result; a box size not breaking into the boundaries set for any given input and output aspect ratio, rather than not breaking out of the boundaries set, you need to compare the starting and resulting aspect ratios, and choose a master dimension based on that.

Making a new scale-side option (I don't know, 'CANVAS' maybe, since you're requesting a resulting minimum resulting canvas side to crop from) for this would require the following logic:

// image dimensions passed to resize
// equivalent value: x:1
$ar = $width/$height;

// the current working image size
$dimensions = getimagesize($file->image_path);

/*
 * Determine which side should be used during resize
 * as the master dimension, so we don't break into our
 * given box size.
 *
 */
if ($dimensions[0] >= $dimensions[1]) { // wide

    // wide enough
    if (($dimensions[0]/$ar) >= $dimensions[1])
        $master = IMAGE::HEIGHT;

    // not wide enough for our ar; it would break into the box
    else
        $master = IMAGE::WIDTH;
}
else { // tall

    // tall enough
    if ($dimensions[0] <= ($dimensions[1]/$ar))
        $master = IMAGE::HEIGHT;

    // not tall enough for our ar; it would break into the box
    else
        $master = IMAGE::WIDTH;
}

I'm not totally sure this would work for tall box-fitting—I didn't actually test that. If not, then you would want to check to see if $ar >= 1 for wide, and have another if block. Nothing too bad.

Change History

Changed 6 months ago by jonathangordon

I think I should point out that this same logic needs to be inverted for keeping images of differing aspect ratios (except a 1:1 resize box) from allowing the image to break out of the requested box size also, which is why this is a bug and not a feature request.

Changed 6 months ago by jonathangordon

  • summary changed from Extending logic on image resize functions to Extending & correcting logic on image resize functions

Changed 5 months ago by jonathangordon

Add const CANVAS = {x}; and the associated check. This is for the GD driver. I assume the exact same logic could be used for ImageMagick?.

http://kohana.pastebin.com/f5eb1d113

Some code was already written to ensure the logic works in reverse, but I haven't actually tested it. It seems like it might work, but I dunno.

An iterative algorithm could indeed solve this in less lines of code, but this is considerably faster than that option, and as it would seem is about as short as it's going to get to cover all 8 input possibilities, 8 tests are required. I tried shortening it to 4 with a few tricks, and it failed on 2 tests, so I just used this.

Changed 3 months ago by Shadowhand

  • owner changed from - No owner - to Shadowhand
  • status changed from new to assigned

Changed 3 months ago by jonathangordon

  • summary changed from Extending & correcting logic on image resize functions to Extending & correcting logic on Image library

While we're at it, let's add some functionality to rotate!

It seems MUCH more useful to let the code do some work for us and rotate (and flip!) an image automagically based on the EXIF data available in the image, for photographs taken with any half-assed camera and up.

I should note that this code is not meant to be cut-and-paste; I ripped it out of my controller.

http://kohana.pastebin.com/f6da6c8ec

Changed 2 months ago by ae

Hey Jonathan, check out ticket:726

This may have solved the problem.

Changed 2 months ago by jonathangordon

ae: Actually, this isn't a bug fix. This describes another technical issue with resizing. While the ticket you linked to prevents an image from going above certain dimensions, this one prevents it from going under certain dimensions.

Note: See TracTickets for help on using tickets.