2

I don't have any experience with PHP and images in general, but I have a need to resize all images into the square when they get uploaded.

Since I have multiple products and they have different pictures that comes in different sizes, I think that the best approach is to 'standardize' them during the upload by taking an image and 'fitting' it into the 800x800 white square while maintaining the aspect ratio (if longest size >800 then downsize, if longest size <800, then re-size).

My initial solution was created via JavaScript, where I tried to find the biggest picture and resize all other images according to it. Although, it is not very useful and can be faulty since if there is a delay in image load, images might not be loaded for JS to perform the operation, thus not showing images at all.

$product = getProductById($productid);

$filesArray = array();


if (isset($_GET['files']) && $productid > 0) {
    $error = false;
    $files = array();
    $fileName = '';

    $uploaddir = "../images/products/";
    foreach ($_FILES as $file) {
        $ext = pathinfo($file['name'], PATHINFO_EXTENSION);
        $random_name = $widgets->randomFileName();
        $randomFullFileName = $productid .'_'. $random_name . '.' . $ext;

        //copy to location
        //----------------
        //HERE I NEED TO CREATE A 800x800px SQUARE and fit the image into it
        //----------------
        if (move_uploaded_file($file['tmp_name'], $uploaddir . $randomFullFileName)) {

            //save to database
            $image_id = updateProduct('default_image', 'images/products/'.$randomFullFileName, $productid);

            if ($image_id > 0) {
                echo 'Added new image';
            } else {
                echo 'Error, unable to add. <br> Please try again.';
            }
        } else {
            echo 'Error, unable to add. <br> Please try again.';
        }
    }
}

Before: 600x300 BEFORE

After: 800x800 with white borders to fill-in the space AFTER

Andrew
  • 7,619
  • 13
  • 63
  • 117
  • 1
    Possible duplicate of [PHP - Place an image over another image](http://stackoverflow.com/questions/23152108/php-place-an-image-over-another-image) – Daniel Nov 26 '15 at 00:44
  • Are you asking to fit multiple images into an `800x800` square, or are you looking to take an image and fit it into an `800x800` square maintaining the aspect ratio and fitting it best horizontally or vertically? – Ohgodwhy Nov 26 '15 at 00:55
  • @Ohgodwhy, #2 - one image at the time – Andrew Nov 26 '15 at 01:11

2 Answers2

4

You can try this approach (tested). It will fit your images into an 800x800 square canvas while maintaining the aspect ratio of your images.

resize_image(): This function will maintain the aspect ratio of your image.

function resize_image($img,$maxwidth,$maxheight) {
    //This function will return the specified dimension(width,height)
    //dimension[0] - width
    //dimension[1] - height

    $dimension = array();
    $imginfo = getimagesize($img);
    $imgwidth = $imginfo[0];
    $imgheight = $imginfo[1];
    if($imgwidth > $maxwidth){
        $ratio = $maxwidth/$imgwidth;
        $newwidth = round($imgwidth*$ratio);
        $newheight = round($imgheight*$ratio);
        if($newheight > $maxheight){
            $ratio = $maxheight/$newheight;
            $dimension[] = round($newwidth*$ratio);
            $dimension[] = round($newheight*$ratio);
            return $dimension;
        }else{
            $dimension[] = $newwidth;
            $dimension[] = $newheight;
            return $dimension;
        }
    }elseif($imgheight > $maxheight){
        $ratio = $maxheight/$imgheight;
        $newwidth = round($imgwidth*$ratio);
        $newheight = round($imgheight*$ratio);
        if($newwidth > $maxwidth){
            $ratio = $maxwidth/$newwidth;
            $dimension[] = round($newwidth*$ratio);
            $dimension[] = round($newheight*$ratio);
            return $dimension;
        }else{
            $dimension[] = $newwidth;
            $dimension[] = $newheight;
            return $dimension;
        }
    }else{
        $dimension[] = $imgwidth;
        $dimension[] = $imgheight;
        return $dimension;
    }
}

And now comes your code,

$product = getProductById($productid);

$filesArray = array();


if (isset($_GET['files']) && $productid > 0) {
    $error = false;
    $files = array();
    $fileName = '';

    $uploaddir = "../images/products/";
    foreach ($_FILES as $file) {
        $ext = pathinfo($file['name'], PATHINFO_EXTENSION);
        $random_name = $widgets->randomFileName();
        $randomFullFileName = $productid .'_'. $random_name . '.' . $ext;

        //copy to location
        //----------------
        //HERE I NEED TO CREATE A 800x800px SQUARE and fit the image into it


        // Create image from file
        $image = null;
        switch(strtolower($file['type']))
        {
            case 'image/jpeg':
                $image = imagecreatefromjpeg($file['tmp_name']);
                break;
            case 'image/png':
                $image = imagecreatefrompng($file['tmp_name']);
                break;
            case 'image/gif':
                $image = imagecreatefromgif($file['tmp_name']);
                break;
            default:
                exit('Unsupported type: '.$file['type']);
        }

        // Get current dimensions
        $old_width  = imagesx($image);
        $old_height = imagesy($image);

        // Get the new dimensions
        $dimension = resize_image($file, 800, 800);
        $new_width  = $dimension[0];
        $new_height = $dimension[1];

        // Create new empty image
        $new = imagecreatetruecolor($new_width, $new_height);

        // Resize old image into new
        imagecopyresampled($new, $image, 0, 0, 0, 0, $new_width, $new_height, $old_width, $old_height);

        // Catch and save the image
        $status = false;
        switch(strtolower($file['type']))
        {
            case 'image/jpeg':
                $status = imagejpeg($new, $uploaddir . $randomFullFileName, 90);
                break;
            case 'image/png':
                $status = imagepng($new, $uploaddir . $randomFullFileName, 0);
                break;
            case 'image/gif':
                $status = imagegif($new, $uploaddir . $randomFullFileName);
                break;
        }

        // Destroy resources
        imagedestroy($image);
        imagedestroy($new);

        //save to database
        if($status){
            $image_id = updateProduct('default_image', 'images/products/'.$randomFullFileName, $productid);

            if ($image_id > 0) {
                echo 'Added new image';
            } else {
                echo 'Error, unable to add. <br> Please try again.';
            }
        }else{
            echo 'Error, unable to add. <br> Please try again.';
        }       

        //----------------
        //if (move_uploaded_file($file['tmp_name'], $uploaddir . $randomFullFileName)) {
        //    //save to database
        //    $image_id = updateProduct('default_image', 'images/products/'.$randomFullFileName, $productid);

        //    if ($image_id > 0) {
        //        echo 'Added new image';
        //    } else {
        //        echo 'Error, unable to add. <br> Please try again.';
        //    }
        //} else {
        //    echo 'Error, unable to add. <br> Please try again.';
        //}

    }
}
Rajdeep Paul
  • 16,887
  • 3
  • 18
  • 37
  • It is interesting- it is kind of working :) the image is not resized and copied 1:1. When adding image 600x300, `$new_width, $new_height, $old_width, $old_height` are 600x300px. Also, `$imginfo = getimagesize($img)` does not work, had to use `$img['tmp_name']` – Andrew Nov 26 '15 at 03:13
  • @Andrew Glad I could help. :) And yes, because the canvas size is 800x800, that's why it keeps the image of size 600x300 as it is. Besides, if you try to stretch an image of size 600x300 to 800x800, the quality of image will degrade. – Rajdeep Paul Nov 26 '15 at 03:40
  • I see, it downsizes the pic to make the longest size no more than specified. That is a good start. Any ideas how to fit it into the white square? – Andrew Nov 26 '15 at 03:42
  • Like I said, if you try to squeeze the image into exact square dimension then it'll degrade the quality of image. – Rajdeep Paul Nov 26 '15 at 03:45
  • I got my answer by combining your answer with this: http://stackoverflow.com/questions/23152108/php-place-an-image-over-another-image – Andrew Nov 26 '15 at 04:02
  • In my case this is not working can anyone help me in it...?? I am taking image from the local directory and create a new image as white background image of loaded image from the local directory.. – Deepak Chawla Oct 03 '18 at 12:57
  • @DeepakChawla If you think the question and/or answer is/are not solving your problem, then feel free to ask a separate question on SO. Just to let you know, simple *not working* is not the right way to give information, please explain your problem clearly i.e. your expected vs. current output, any visible errors etc. – Rajdeep Paul Nov 12 '18 at 07:08
1

Original answer

How about imagine?

Insert this code before //save to database comment:

<?php
$imagine = new Imagine\Gd\Imagine();
$size = new Imagine\Image\Box(800, 800);
$mode = Imagine\Image\ImageInterface::THUMBNAIL_INSET;
$imagine
    ->open($uploaddir . $randomFullFileName)
    ->thumbnail($size, $mode)
    ->save($uploaddir . $randomFullFileName);

New answer

As resize is not working like expected (thanks to @Pradeep Sanjaya), I would paste solution based on snippet from link:

/**
 * Image resize
 * @param string $input Full path to source image
 * @param string $output Full path to result image
 * @param int $width Width of result image
 * @param int $height Height of result image
 */
function resizeImage($input, $output, $width, $height)
{
    $imagine = new Imagine\Gd\Imagine();
    $size = new Imagine\Image\Box($width, $height);
    $mode = Imagine\Image\ImageInterface::THUMBNAIL_INSET;
    $resizeimg = $imagine
        ->open($input)
        ->thumbnail($size, $mode);
    $sizeR = $resizeimg->getSize();
    $widthR = $sizeR->getWidth();
    $heightR = $sizeR->getHeight();

    $preserve = $imagine->create($size);
    $startX = $startY = 0;
    if ($widthR < $width) {
        $startX = ($width - $widthR) / 2;
    }
    if ($heightR < $height) {
        $startY = ($height - $heightR) / 2;
    }
    $preserve
        ->paste($resizeimg, new Imagine\Image\Point($startX, $startY))
        ->save($output);
}

And usage according to original question:

<?php
// placed after `save to database` comment
resizeImage(
    $uploaddir . $randomFullFileNamem,
    $uploaddir . $randomFullFileName,
    800, 800
);
userlond
  • 3,632
  • 2
  • 36
  • 53
  • 1
    I have tested this with PHP 5.5.9, GD 2.1.1-dev FreeType Support enabled with FreeType Version => 2.5.2 and it did not scale as expected. I found following blog which explain scaling [link](http://harikt.com/blog/2012/12/17/resize-image-keeping-aspect-ratio-in-imagine/) – Pradeep Sanjaya Nov 26 '15 at 04:40