0

Im trying to create with php a 4:3 image with any image uploaded by user. No matter the image original size, i want to fill the background with a blurred copy of the same image.

This is the code i use (from István Ujj-Mészáros):

function resize($source_image, $destination, $tn_w, $tn_h, $quality = 90) {

    $info = getimagesize($source_image);
    $imgtype = image_type_to_mime_type($info[2]);

    #assuming the mime type is correct
    switch ($imgtype) {
        case 'image/jpeg':
            $source = imagecreatefromjpeg($source_image);
            break;
        case 'image/gif':
            $source = imagecreatefromgif($source_image);
            break;
        case 'image/png':
            $source = imagecreatefrompng($source_image);
            break;
        default:
            die('Invalid image type.');
    }

    #Figure out the dimensions of the image and the dimensions of the desired thumbnail
    $src_w = imagesx($source);
    $src_h = imagesy($source);

    #Do some math to figure out which way we'll need to crop the image
    #to get it proportional to the new size, then crop or adjust as needed
    $x_ratio = $tn_w / $src_w;
    $y_ratio = $tn_h / $src_h;

    if (($src_w <= $tn_w) && ($src_h <= $tn_h)) {
        $new_w = $src_w;
        $new_h = $src_h;
    } elseif (($x_ratio * $src_h) < $tn_h) {
        $new_h = ceil($x_ratio * $src_h);
        $new_w = $tn_w;
    } else {
        $new_w = ceil($y_ratio * $src_w);
        $new_h = $tn_h;
    }

    $newpic = imagecreatetruecolor(round($new_w), round($new_h));
    imagecopyresampled($newpic, $source, 0, 0, 0, 0, $new_w, $new_h, $src_w, $src_h);
    $final = imagecreatetruecolor($tn_w, $tn_h);

    // This code fill with green color
    //$backgroundColor = imagecolorallocate($final, 0, 255, 0);
    //imagefill($final, 0, 0, $backgroundColor);
    imagecopy($final, $newpic, (($tn_w - $new_w)/ 2), (($tn_h - $new_h) / 2), 0, 0, $new_w, $new_h);

    // This code generates a blurred image
    # ****************************************************
    //for ($x=1; $x <=2; $x++){
    //    imagefilter($final, IMG_FILTER_GAUSSIAN_BLUR, 999);
    //} 
    //imagefilter($final, IMG_FILTER_SMOOTH,99);
    //imagefilter($final, IMG_FILTER_BRIGHTNESS, 10);  
    # ****************************************************

    if (imagejpeg($final, $destination, $quality)) {
        return true;
    }
    return false;
}

// targetFilePath contains the folder an filename
resize($targetFilePath,$targetFilePath,640,480,90);

The result is like this image: my result until now

What do i need? The result that i hope

Please any idea will be welcome. Thank you in advance!!!

mhuenchul
  • 43
  • 1
  • 10

3 Answers3

2

I enhanced @mhuenchul code and it works now whatever the image size is.

function image_blurred_bg($image, $dest, $width, $height){
try{
    $info = getimagesize($image);
} catch (Exception $e){
    return false;
}

$mimetype = image_type_to_mime_type($info[2]);
switch ($mimetype) {
    case 'image/jpeg':
        $image = imagecreatefromjpeg($image);
        break;
    case 'image/gif':
        $image = imagecreatefromgif($image);
        break;
    case 'image/png':
        $image = imagecreatefrompng($image);
        break;
    default:
        return false;
}

$wor = imagesx($image);
$hor = imagesy($image);
$back = imagecreatetruecolor($width, $height);

$maxfact = max($width/$wor, $height/$hor);
$new_w = $wor*$maxfact;
$new_h = $hor*$maxfact;
imagecopyresampled($back, $image, -(($new_w-$width)/2), -(($new_h-$height)/2), 0, 0, $new_w, $new_h, $wor, $hor);

// Blur Image
for ($x=1; $x <=40; $x++){
    imagefilter($back, IMG_FILTER_GAUSSIAN_BLUR, 999);
}
imagefilter($back, IMG_FILTER_SMOOTH,99);
imagefilter($back, IMG_FILTER_BRIGHTNESS, 10);

$minfact = min($width/$wor, $height/$hor);
$new_w = $wor*$minfact;
$new_h = $hor*$minfact;

$front = imagecreatetruecolor($new_w, $new_h);
imagecopyresampled($front, $image, 0, 0, 0, 0, $new_w, $new_h, $wor, $hor);

imagecopymerge($back, $front,-(($new_w-$width)/2), -(($new_h-$height)/2), 0, 0, $new_w, $new_h, 100);

// output new file
imagejpeg($back,$dest,90);
imagedestroy($back);
imagedestroy($front);

return true;
}
Appoodeh
  • 104
  • 1
  • 8
  • You should add more explanation about what and why you've changed. It won't help much if someone who will find this question won't understand how you've improved the accepted answer. – Michal Hynčica Nov 26 '19 at 22:06
  • The accepted answer was not working correctly if the image height is greater than width so I removed all unnecessary code's lines and altered the math equation that calculate the new size and test it on multiple images size – Appoodeh Nov 26 '19 at 22:16
  • 1
    Thank you @Appoodeh Your improvements on code are awesome! Your code works really fine! – mhuenchul Nov 27 '19 at 02:44
  • 1
    Worked with almost not modification on my part. Great code!. Although it would be nice to see some comments so we can understand the steps. – Kristifer Szabo Oct 12 '22 at 06:11
1

There are many approaches, but I would suggest you use imagecopymerge instead of imagecopy. You provide the destination and source coordinates as well as the source size and voila!

However note that this way you won't keep transparency (for GIF/PNG, if present). To do it, have a look at this comment of Sina Salek in the PHP documentation: PNG ALPHA CHANNEL SUPPORT for imagecopymerge().

But I would agree with @LeeKowalkowski - in the long run, you should consider migrating to ImageMagick for many reasons - image quality above all.

EDIT: I forgot to mention, before merging, set transparent colour (the extended canvas) with imagecolortransparent. Then, Sina Salek's comment in PHP documentation (the link above).

0

Ok, i did my work and studied more about php image commands. I wrote a solution that works very well.

<?php

$image = "01.jpg";

image_web($image, 700, 525); // I need final images 700x525 (4:3)

echo '<img src="00.jpg"/>';

function image_web($image, $width, $height){ // Get the image source and the final desire dimensions
    $info = getimagesize($image);
    //$mimetype = $info['mime']; // other way to get mimetype
    $mimetype = image_type_to_mime_type($info[2]);
    $allowTypes = array('image/jpeg','image/png','image/gif');    
    if(in_array($mimetype, $allowTypes)){
        switch ($mimetype) {
            case 'image/jpeg':
                $image = imagecreatefromjpeg($image);
                break;
            case 'image/gif':
                $image = imagecreatefromgif($image);
                break;
            case 'image/png':
                $image = imagecreatefrompng($image);
                break;
            default:
                die('Invalid image type.');
        }
    } else {
        echo 'Is not a image';
    }
    $image2 = $image; // Save a copy to be used for front image
    $wor = imagesx($image); // Get original image width
    $hor = imagesy($image); // Get original image height
    if ($hor >= $wor){ // If is vertical*******************************************************************************************************
        if ($wor >= $width){ // If image source is bigger than final desire dimensions
            $hcenter = ($hor/2)-($height/2); // center image source in height
            $back = imagecreatetruecolor(round($width), round($height));
            imagecopyresampled($back, $image, 0, -$hcenter, 0, 0, $wor, $hor, $wor, $hor);
        } else { // If image source is not bigger than final desire dimensions
            $hcenter = ($hor/2)-($height/2); // center image source in height
            $hnu = ($hor*$width)/$wor;
            $back = imagecreatetruecolor(round($width), round($height));
            imagecopyresampled($back, $image, 0, -$hcenter, 0, 0, $width, $hnu, $wor, $hor);
        }
    } else { // If is portrait rectangular****************************************************************************************************  
        $ratio = $wor/$hor;
        if($ratio > 1.3333333){ // If is portrait larger than 4:3       
            $wnu = ($wor*$height)/$hor;
            $wcenter = ($wnu/2)-($width/2); // center image in width
            $back = imagecreatetruecolor(round($width), round($height));
            imagecopyresampled($back, $image, -$wcenter, 0, 0, 0, $wnu, $height, $wor, $hor); 
        } else { // If portrait is not larger than 4:3
            $hnu = ($wor*$height)/$hor;
            $hcenter = ($hnu/2)-($height/2); // center image source in height
            $back = imagecreatetruecolor(round($width), round($height));
            imagecopyresampled($back, $image, 0, -$hcenter, 0, 0, $width, $hnu, $wor, $hor); 
        }
    }
    // Blur Image
    for ($x=1; $x <=40; $x++){
        imagefilter($back, IMG_FILTER_GAUSSIAN_BLUR, 999);
    } 
    imagefilter($back, IMG_FILTER_SMOOTH,99);
    imagefilter($back, IMG_FILTER_BRIGHTNESS, 10);
    // Getting the dimensions of the image
    $src_w = imagesx($image2);
    $src_h = imagesy($image2);
    // Do some math to figure out which way we'll need to crop the image
    // to get it proportional to the new size, then crop or adjust as needed
    $x_ratio = $width / $src_w;
    $y_ratio = $height / $src_h;
    if (($src_w <= $width) && ($src_h <= $height)) {
        $new_w = $src_w;
        $new_h = $src_h;
    } elseif (($x_ratio * $src_h) < $height) {
        $new_h = ceil($x_ratio * $src_h);
        $new_w = $width;
    } else {
        $new_w = ceil($y_ratio * $src_w);
        $new_h = $height;
    }
    $front = imagecreatetruecolor(round($new_w), round($new_h));
    imagecopyresampled($front, $image2, 0, 0, 0, 0, $new_w, $new_h, $src_w, $src_h);
    if ($new_h >= $new_w){ // If is vertical image
        $wctr = ($new_w/2)-($width/2);
        imagecopymerge($back, $front,-$wctr, 0, 0, 0, $new_w, $new_h, 100);
    } else { // if is portrait
        $hctr = ($new_h/2)-($height/2);
        imagecopymerge($back, $front,0, -$hctr, 0, 0, $new_w, $new_h, 100);
    }
    // output new file
    imagejpeg($back,'00.jpg',90);
    imagedestroy($back);
    imagedestroy($front);
    //*********************************************************************************
    /**
    Do other actions like send ajax responses, save in database, etc
    **/
}

?>
Dharman
  • 30,962
  • 25
  • 85
  • 135
mhuenchul
  • 43
  • 1
  • 10