Welcome Guest, Not a member yet? Register   Sign In
Image library's maintain_ratio flawed?
#1

[eluser]Unknown[/eluser]
Hi,

this has been discussed several times, and there is even a bug report regarding this problem, but for reasons beyond me, no one has taken 15 minutes to implement a simple fix for this. The problem is that the maintain_ratio setting for the image library behaves unexpectedly and illogically.

The whole point of maintaining an aspect ratio is that you should be able to provide either maximum allowed width OR height. If width is specified, then height should be calculated automatically and vice versa. However, in CI's image library, BOTH height AND width need to be specified for this to work, as seen from the following piece of code found at the beginning of image_reproportion() function
Code:
if ( ! is_numeric($this->width) OR ! is_numeric($this->height) OR $this->width == 0 OR $this->height == 0) return;

For example, if I want to create an image with maximum width 500 on my page, and define the config in the following manner:
Code:
//Set resizing options
$config['image_library'] = 'gd2';
$config['source_image'] = $src;
$config['new_image'] = $dest;
$config['maintain_ratio'] = TRUE;
$config['width'] = 500;
It will resize the image to 500 in width, but keep the height equal to the one of the original image, essentially distorting the final image.

In my opinion this is a BUG, and a serious one. I know I can write my own helper that will calculate height in the appropriate aspect ratio, but I don't know why I should be forced to do this as the only logical place for that function would be inside the image library. It is very easy to fix. Please let me know if I am mistaken.
#2

[eluser]Unknown[/eluser]
Here's a quick fix that I came up with. Tested it with some expected input and it seems to behave as expected

New image_reproportion function

Code:
function image_reproportion()
    {
        if ( ! is_numeric($this->width) OR ! is_numeric($this->height) OR ($this->width == 0 AND $this->height == 0))
            return;
        
        if ( ! is_numeric($this->orig_width) OR ! is_numeric($this->orig_height) OR $this->orig_width == 0 OR $this->orig_height == 0)
            return;
        
        $new_width    = ceil($this->orig_width*$this->height/$this->orig_height);        
        $new_height    = ceil($this->width*$this->orig_height/$this->orig_width);
          
        if($this->height == 0 OR $this->width == 0)
        {
            $this->master_dim = ($this->width == 0) ? 'height' : 'width';
        }
          
        if ($this->master_dim != 'width' AND $this->master_dim != 'height')
        {
            $ratio = (($this->orig_height/$this->orig_width) - ($this->height/$this->width));            
            $this->master_dim = ($ratio < 0) ? 'width' : 'height';
        }
        
        if (($this->width != $new_width) OR ($this->height != $new_height))
        {
            if ($this->master_dim == 'height')
            {
                $this->width = $new_width;
            }
            else
            {
                $this->height = $new_height;
            }
        }
    }

And in the initialize function replace this:
Code:
if ($this->maintain_ratio === TRUE && ($this->width != '' AND $this->height != ''))
        {
            $this->image_reproportion();
        }
with the following:
Code:
if ($this->maintain_ratio === TRUE && ($this->width != '' OR $this->height != ''))
        {
            $this->image_reproportion();
        }

With this implemented the resize() operation will accept any of the following sets of input:
width only
height only
width and height
And will work as expected in all 3 scenarios.
#3

[eluser]Ichabodcole[/eluser]
@Kosta, ran into the same issue. I initially came to the same fix as you, but then used another fix by just putting the width and height checking code that directly proceeds the image reproportion code above the reproportion code.
Original Code
Code:
/*
         * Should we maintain image proportions?
         *
         * When creating thumbs or copies, the target width/height
         * might not be in correct proportion with the source
         * image's width/height.  We'll recalculate it here.
         *
         */
        if ($this->maintain_ratio === TRUE && ($this->width != '' AND $this->height != ''))
        {
            $this->image_reproportion();
        }

        /*
         * Was a width and height specified?
         *
         * If the destination width/height was
         * not submitted we will use the values
         * from the actual file
         *
         */
        if ($this->width == '')
            $this->width = $this->orig_width;

        if ($this->height == '')
            $this->height = $this->orig_height;

Switched Code
Code:
/*
         * Was a width and height specified?
         *
         * If the destination width/height was
         * not submitted we will use the values
         * from the actual file
         *
         */
        if ($this->width == '')
            $this->width = $this->orig_width;

        if ($this->height == '')
            $this->height = $this->orig_height;

        /*
         * Should we maintain image proportions?
         *
         * When creating thumbs or copies, the target width/height
         * might not be in correct proportion with the source
         * image's width/height.  We'll recalculate it here.
         *
         */
        if ($this->maintain_ratio === TRUE && ($this->width != '' AND $this->height != ''))
        {
            $this->image_reproportion();
        }


I also find it very odd that this has not been fixed. Even if it's not technically a "bug" (although, I'd say it is), it seems silly not to update it. I hope these are cleared up in 2.0




Theme © iAndrew 2016 - Forum software by © MyBB