EpicKnarvik97
EpicKnarvik97

Reputation: 165

PHP Convert image to specific height and width without stretching

I am trying to make thumbnails of images I have lying around. They have all kinds of resolutions, but I want to create thumbnails which are 225 by 150 in size. What I have been trying to do, is to directly transform either the width or height (depending on what works best) and use a centered part of the original image. For some images it works fine, but for others it fails horribly.

The direct logic between what I want to do:

if the width is fine, and the height is big:
   use the width as is
   calculate height - the height which would go with width for the thumbnail ratio.
else
    use the height as is
    calculate width - the width which would go with height for the thumbnail ratio

This would give the part of the image that is not used. It is used as x and y offsets. I also reduce the size of the part of the image being used.

I have a function I use for thumbnails, but I am unsure of the relation between the ratio and the actual width and height:

function shrinkImage( $owidth, $oheight, $filename, $newFile ) {
    if ( ($img_info = getimagesize( $filename ) ) === FALSE) {
        die("Image not found or not an image");
    }

    switch ( $img_info[2] ) {
        case IMAGETYPE_GIF  :
            $image = imagecreatefromgif( $filename);
            break;
        case IMAGETYPE_JPEG :
            $image = imagecreatefromjpeg( $filename );
            break;
        case IMAGETYPE_PNG  :
            $image = imagecreatefrompng( $filename );
            break;
        default :
            die( "Unknown filetype" );
    }

    $thumb_width = 225;
    $thumb_height = 150;

    if( ($oheight/$thumb_height) < ($owidth/$thumb_width) ) {
        $y = 0;
        $x = $owidth - ($oheight * $thumb_width / $thumb_height);
    } else {
        $x = 0;
        $y = $oheight - (($owidth * $thumb_height) / $thumb_width);
    }

    $thumb = imagecreatetruecolor( $thumb_width, $thumb_height );
    imagecopyresampled( $thumb, $image, 0, 0, $x, $y, $thumb_width, $thumb_height, $owidth - ($x * 2), $oheight - ($y * 2));

    switch ( $img_info[2] ) {
        case IMAGETYPE_GIF  :
            imagegif( $thumb,  $newFile );
            break;
        case IMAGETYPE_JPEG :
            imagejpeg( $thumb, $newFile, 100 );
            break;
        case IMAGETYPE_PNG  :
            imagepng($thumb,  $newFile, 0 );
            break;
        default :
            die("Unknown filetype");
    }
    return True;
}

Here is an example of an original vs a cropped image: The original image The cropped image

This is not the kind of thumbnails my code produces, but an example of what I want it to do.

Edit:

if( ($oheight/$thumb_height) < ($owidth/$thumb_width) ) {
    $y = 0;
    $x = $owidth - ($oheight * $thumb_width / $thumb_height);
} else {
    $x = 0;
    $y = $oheight - ($owidth * $thumb_height / $thumb_width * 2);
}

Works for tall images, and some normal images, but creates some horrible lines for wide images.A sample of code result

Upvotes: 0

Views: 1236

Answers (1)

EpicKnarvik97
EpicKnarvik97

Reputation: 165

After digging up some long lost mathematics knowledge, I found a working solution:

    $thumb_width = 225;
    $thumb_height = 150;

    if( ($owidth/$thumb_width) > ($oheight/$thumb_height) ) {
        $y = 0;
        $x = $owidth - ( ($oheight * $thumb_width) / $thumb_height);
    } else {
        $x = 0;
        $y = $oheight - ( ($owidth * $thumb_height) / $thumb_width);
    }

    $thumb = imagecreatetruecolor( $thumb_width, $thumb_height );
    imagecopyresampled( $thumb, $image, 0, 0, $x/2, $y/2, $thumb_width, $thumb_height, $owidth - $x, $oheight - $y);

Upvotes: 2

Related Questions