How to resize image keeping constraints php

2020-04-11 04:07发布

I have made two GIFs to explain what I am trying to do. Where the grey border is the dimensions I am after (700*525). They are at the bottom of this question.

I want for all images that are larger than the given width and height to scale down to the border (from the centre) and then crop off the edges. Here is some code I have put together to attempt this:

if ($heightofimage => 700 && $widthofimage => 525){
    if ($heightofimage > $widthofimage){

        $widthofimage = 525;
        $heightofimage = //scaled height.

        //crop height to 700.

    }

    if ($heightofimage < $widthofimage){

        $widthofimage = //scaled width.
        $heightofimage = 700;

        //crop width to 525.

    }
}else{
    echo "image too small";
}

Here are some GIFs that visually explain what I am trying to achieve:

GIF 1: Here the image proportions are too much in the x direction

enter image description here

GIF 2: Here the image proportions are too much in the y direction

enter image description here


image quality comparison for @timclutton

so I have used your method with PHP (click here to do your own test with the php) and then compared it to the original photo as you can see there is a big difference!:

Your PHP method:

enter image description here
(source: tragicclothing.co.uk)

The actual file:

enter image description here


标签: php html image
4条回答
我想做一个坏孩纸
2楼-- · 2020-04-11 04:25

I have used GD library to accomplish the resize. Basically what I did is, I calculated the image dimension and then resized the image to dimension 700x525 from the center.

<?php
/*
 * PHP GD
 * resize an image using GD library
 */

//the image has 700X525 px ie 4:3 ratio
$src = 'demo_files/bobo.jpg';

// Get new sizes
list($width, $height) = getimagesize($src);

$x = 0;
$y = 0;
if($width < $height){
    $newwidth = $width;
    $newheight = 3/4 * $width;
    $x = 0;
    $y = $height/2 - $newheight/2;
}else{
    $newheight = $height;
    $newwidth = 4/3 * $height;
    $x=$width/2 - $newwidth/2;
    $y=0;

}

$targ_w = 700; //width of the image to be resized to
$targ_h = 525; ////height of the image to be resized to
$jpeg_quality = 90;

$img_r = imagecreatefromjpeg($src);
$dst_r = ImageCreateTrueColor( $targ_w, $targ_h );

imagecopyresampled($dst_r,$img_r,0,0,$x,$y,$targ_w,$targ_h,$newwidth,$newheight);

header('Content-type: image/jpeg');
imagejpeg($dst_r,null,$jpeg_quality);

exit;

?>
查看更多
我命由我不由天
3楼-- · 2020-04-11 04:36

The below code should do what you want. I've not tested it extensively but it seems to work on the few test images I made. There's a niggling doubt at the back of mind that somewhere my math is wrong, but it's late and I can't see anything obvious.

Edit: It niggled enough I went through again and found the bug, which was that the crop wasn't in the middle of the image. Code replaced with working version.

In short: treat this as a starting point, not production-ready code!

<?php

// set image size constraints.
$target_w = 525;
$target_h = 700;

// get image.
$in = imagecreatefrompng('<path to your>.png');

// get image dimensions.
$w = imagesx($in);
$h = imagesy($in);

if ($w >= $target_w && $h >= $target_h) {
    // get scales.
    $x_scale = ($w / $target_w);
    $y_scale = ($h / $target_h);

    // create new image.
    $out = imagecreatetruecolor($target_w, $target_h);

    $new_w = $target_w;
    $new_h = $target_h;
    $src_x = 0;
    $src_y = 0;

    // compare scales to ensure we crop whichever is smaller: top/bottom or
    // left/right.
    if ($x_scale > $y_scale) {
        $new_w = $w / $y_scale;

        // see description of $src_y, below.
        $src_x = (($new_w - $target_w) / 2) * $y_scale;
    } else {
        $new_h = $h / $x_scale;

        // a bit tricky. crop is done by specifying coordinates to copy from in
        // source image. so calculate how much to remove from new image and
        // then scale that up to original. result is out by ~1px but good enough.
        $src_y = (($new_h - $target_h) / 2) * $x_scale;
    }

    // given the right inputs, this takes care of crop and resize and gives
    // back the new image. note that imagecopyresized() is possibly quicker, but
    // imagecopyresampled() gives better quality.
    imagecopyresampled($out, $in, 0, 0, $src_x, $src_y, $new_w, $new_h, $w, $h);

    // output to browser.
    header('Content-Type: image/png');
    imagepng($out);
    exit;

} else {
    echo 'image too small';
}

?>
查看更多
贼婆χ
4楼-- · 2020-04-11 04:40

Using Imagick :

define('PHOTO_WIDTH_THUMB', 700);
define('PHOTO_HEIGHT_THUMB', 525);

$image = new Imagick();
$image->readImage($file_source);
$width = $image->getImageWidth();
$height = $image->getImageHeight();

if($width > $height){
  $image->thumbnailImage(0, PHOTO_HEIGHT_THUMB);
}else{
  $image->thumbnailImage(PHOTO_WIDTH_THUMB, 0);
}

$thumb_width = $image->getImageWidth();
$thumb_height = $image->getImageHeight();
$x = ($thumb_width - PHOTO_WIDTH_THUMB)/2;
$y = ($thumb_height - PHOTO_HEIGHT_THUMB)/2;
$image->cropImage(PHOTO_THUMB_WIDTH, PHOTO_THUMB_HEIGHT, $x, $y);
$image->writeImage($thumb_destination);

$image->clear();
$image->destroy();
unlink($file_source);
查看更多
成全新的幸福
5楼-- · 2020-04-11 04:48

i used http://phpthumb.sourceforge.net to have a beutiful solution also with transparent curved edges.

this is an alternative route to solution, might suit someone's need with little configuration.

查看更多
登录 后发表回答