tags:

views:

54

answers:

1

Hi, I use a class that automatically crops an image as a square based on some options. The problem is that when the image is of a certain width and height, the image is cropped but a 1px column of black pixels is added to the right of the image. I think that the problem is in the mathematics used to generate the new image size... Maybe when the division of the height and the width gives a decimal number then the square is not perfect and the black pixels are added...

Any solution?

This is how I call the object:

$resizeObj = new resize($image_file); // *** 1) Initialise / load image
            $resizeObj -> resizeImage(182, 182, 'crop'); // *** 2) Resize image
            $resizeObj -> saveImage($destination_path, 92); // *** 3) Save image

The part of the class I'm talking about:

private function getOptimalCrop($newWidth, $newHeight)
    {

        $heightRatio = $this->height / $newHeight;
        $widthRatio  = $this->width /  $newWidth;

        if ($heightRatio < $widthRatio) {
            $optimalRatio = $heightRatio;
        } else {
            $optimalRatio = $widthRatio;
        }

        $optimalHeight = $this->height / $optimalRatio;
        $optimalWidth  = $this->width  / $optimalRatio;

        return array('optimalWidth' => $optimalWidth, 'optimalHeight' => $optimalHeight);
    }

    private function crop($optimalWidth, $optimalHeight, $newWidth, $newHeight)
    {
        // *** Find center - this will be used for the crop
        $cropStartX = ( $optimalWidth / 2) - ( $newWidth /2 );
        $cropStartY = 0; // start crop from top

        $crop = $this->imageResized;
        //imagedestroy($this->imageResized);

        // *** Now crop from center to exact requested size
        $this->imageResized = imagecreatetruecolor($newWidth , $newHeight);
        imagecopyresampled($this->imageResized, $crop , 0, 0, $cropStartX, $cropStartY, $newWidth, $newHeight , $newWidth, $newHeight);
    }

Update:

Maybe changing this:

$heightRatio = $this->height / $newHeight;
$widthRatio  = $this->width /  $newWidth;

with this:

$heightRatio = round($this->height / $newHeight);
$widthRatio  = round($this->width /  $newWidth);
A: 

This line:

$cropStartX = ( $optimalWidth / 2) - ( $newWidth /2 );

looks suspicious.

If this is integer division then for images that are an odd number of pixels wide you'll get truncation. Try:

$cropStartX = ( $optimalWidth / 2.0) - ( $newWidth / 2.0 );

Make sure that all your arithmetic is using real numbers, preferably double precision ones, but with numbers in the range you are dealing with it should be OK to work in single precision floats.

ChrisF
How to make sure that all the arithmetic is using real numbers??
Jonathan
@Jonathan - If this were C# or C++ I'd say declare them as `double`, but as PHP isn't strongly typed I'm not sure there's a "correct" way.
ChrisF