调整图像大小并将每个图像调整为方形保持纵横比(后端)

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

dtrz17917
dtrz17917 #2-当时的一张图片
接近 5 年之前 回复
dstwfcz1377
dstwfcz1377 您是要求将多个图像放入800x800正方形中,还是想要拍摄图像并将其放入800x800正方形中,保持纵横比并在水平或垂直方向上进行最佳拟合?
接近 5 年之前 回复
dqz7636
dqz7636 PHP的可能重复-将图像放在另一个图像上
接近 5 年之前 回复

2个回答

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.';
        //}

    }
}
duanjia8215
duanjia8215 如果您认为问题和/或答案没有解决您的问题,那么请随意提出一个单独的问题。 只是为了让您知道,简单的不工作不是提供信息的正确方法,请清楚地解释您的问题,即您的预期与当前输出,任何可见错误等。
接近 2 年之前 回复
dongzongzhi6953
dongzongzhi6953 在我的情况下,这是行不通的任何人都可以帮助我... ?? 我从本地目录中获取图像,并从本地目录创建一个新图像作为加载图像的白色背景图像。
接近 2 年之前 回复
duanmiao6695
duanmiao6695 那很整洁! :)
接近 5 年之前 回复
dongzhang1864
dongzhang1864 我把你的答案与这个结合起来得到了答案:stackoverflow.com/questions/23152108 / ...
接近 5 年之前 回复
duanmou9228
duanmou9228 就像我说的,如果你试图将图像压缩到精确的方形尺寸,那么它会降低图像的质量。
接近 5 年之前 回复
doujiao8491
doujiao8491 我看,它缩小了pic的尺寸,使最长的尺寸不超过规定值。 这是一个好的开始。 任何想法如何适应白色方块?
接近 5 年之前 回复
duanraotun1674
duanraotun1674 很高兴我能帮助你。 :)是的,因为画布大小是800x800,这就是为什么它保持600x300大小的图像。 此外,如果您尝试将尺寸为600x300的图像拉伸到800x800,图像质量会降低。
接近 5 年之前 回复
dqayok7935
dqayok7935 有趣的是 - 它有点工作:)图像没有调整大小并以1:1复制。 添加图像600x300时,$ new_width,$ new_height,$ old_width,$ old_height为600x300px。 另外,$ imginfo = getimagesize($ img)不起作用,不得不使用$ img ['tmp_name']
接近 5 年之前 回复



原始答案</ h2>

如何想象一下?</ p>

// save to database </ code> comment之前插入此代码:</ p>

 &lt;?php 
$ imagine = new想象\ Gd \ Imagine();
$ size = new想象\ Image \ Box(800,800);
$ mode = Imagine \ Image \ ImageInterface :: THUMBNAIL_INSET;
$ imagine
  • &gt; open($ uploaddir。$ randomFullFileName)
  • &gt;缩略图($ size,$ mode)
  • &gt; save($ uploaddir 。$ randomFullFileName);
    </ code> </ pre>

    新答案</ h2>

    由于调整大小不能正常工作(感谢@Pradeep Sanjaya), 我会根据来自的片段粘贴解决方案 链接:</ p>

    </ p>

      / ** 
    *图片大小调整
    • @param string $ input完整路径 source image
    • @param string $ output结果图像的完整路径
    • @param int $ width Width 结果图像
    • @param int $ height结果图像的高度
    • / function resizeImage($ input,$ output,$ width,$ height) { $ imag = new Imagine \ Gd \ Imagine( ); $ size = new Imagine \ Image \ Box($ width,$ height); $ mode = Imagine \ Image \ ImageInterface :: THUMBNAIL_INSET; $ resizeimg = $ imagine
  • &gt; open($ 输入)

  • &gt;缩略图($ size,$ mode);
    $ sizeR = $ resizeimg-&gt; getSize();
    $ widthR = $ sizeR-&gt; getWidth();
    $ heightR = $ sizeR-&gt; getHeight();

    $ preserve = $ imag-&gt; create($ size);
    $ startX = $ startY = 0;
    if($ widthR&lt; $ width){
    $ startX =($ width - $ widthR)/ 2;
    }
    if($ heightR&lt; $ height){
    $ startY =($ height - $ heightR)/ 2; \ n}
    $ preserve

  • &gt;粘贴($ resizeimg,new Imagine \ Image \ Point($ startX,$ startY))

  • &gt; save($ output);
    }
    </ code> </ pre>

    根据原始问题的用法:</ p>

     &lt;?php 
    //放在`保存到数据库'后注释


    $ uploaddir。$ randomFullFileNamem,
    $ uploaddir。$ randomFullFileName,
    800,800
    );
    </ code> </ pre>
    </ div>

展开原文

原文

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
);

doubu0897
doubu0897 你是对的,我已经开心了:)
接近 5 年之前 回复
dpqjvoq9033
dpqjvoq9033 我已经使用PHP 5.5.9测试了这一点,使用FreeType Version => 2.5.2启用了GD 2.1.1-dev FreeType支持,并且没有按预期进行扩展。 我发现以下博客解释缩放链接
接近 5 年之前 回复
Csdn user default icon
上传中...
上传图片
插入图片
抄袭、复制答案,以达到刷声望分或其他目的的行为,在CSDN问答是严格禁止的,一经发现立刻封号。是时候展现真正的技术了!
立即提问
相关内容推荐