【问题标题】:PHP Image resize - Why is the image uploaded but not resized?PHP Image resize - 为什么图片上传但没有调整大小?
【发布时间】:2011-01-26 18:33:17
【问题描述】:

背景
我有一个上传图片的脚本。一个保留原始图像,一个调整图像大小。 1. 如果图像尺寸(宽度和高度)在最大尺寸内,我使用简单的“复制”直接到文件夹 UserPics。 2.如果原始尺寸大于最大尺寸,我想将宽度和高度调整为最大尺寸。 他们都在将图片上传到文件夹中,但是在第二种情况下,图片不会被调整大小。

问题
脚本有问题吗?
设置有问题吗?

设置
服务器:WAMP 2.0
PHP:5.3.0
PHP.ini:启用 GD2,内存=128M(已尝试 1000M)
尝试上传的图像类型:jpg、jpeg、gif 和 png(所有这些都相同)

脚本

if (isset($_POST['adduserpic'])) {  
    // Check errors on file  
    if ($_FILES["file"]["error"] > 0) {  
        echo $_FILES["file"]["error"]." errors<br>";  
    } else {  
        $image =$_FILES["file"]["name"];  
        $uploadedfile = $_FILES["file"]["tmp_name"];  
    //Uploaded image  
    $filename = stripslashes($_FILES['file']['name']);  

    //Read filetype  
    $i = strrpos($filename,".");  
    if (!$i) { return ""; }  
    $l = strlen($filename) - $i;  
    $extension = substr($filename,$i+1,$l);  
    $extension = strtolower($extension);  

    //New picture name = maxid+1 (from database)  
    $query = mysql_query("SELECT MAX(PicId) AS number FROM userpictures");  
    $row = mysql_fetch_array($query);  
    $imagenumber = $row['number']+1;  

    //New name of image (including path)   
    $image_name=$imagenumber.'.'.$extension;    
    $newname = "UserPics/".$image_name;  

    //Check width and height of uploaded image  
    list($width,$height)=getimagesize($uploadedfile);  

    //Check memory to hold this image (added only as checkup)   
    $imageInfo = getimagesize($uploadedfile);   
    $requiredMemoryMB = ( $imageInfo[0] * $imageInfo[1] * ($imageInfo['bits'] / 8) * $imageInfo['channels'] * 2.5 ) / 1024;  
    echo $requiredMemoryMB."<br>";  

    //Max dimensions that can be uploaded  
    $maxwidth = 20;  
    $maxheight = 20;  

    // Check if dimensions shall be original  
    if ($width > $maxwidth || $height > $maxheight) {  
        //Make jpeg from uploaded image  
        if ($extension=="jpg" || $extension=="jpeg" || $extension=="pjpeg" ) {  
            $modifiedimage = imagecreatefromjpeg($uploadedfile);  
        } elseif ($extension=="png") {  
            $modifiedimage = imagecreatefrompng($uploadedfile);  
        } elseif ($extension=="gif") {  
            $modifiedimage = imagecreatefromgif($uploadedfile);  
        }   
        //Change dimensions  
        if ($width > $height) {  
            $newwidth = $maxwidth;  
            $newheight = ($height/$width)*$newwidth;  
        } else {  
            $newheight = $maxheight;  
            $newwidth = ($width/$height)*$newheight;  
        }  

        //Create new image with new dimensions  
        $newdim = imagecreatetruecolor($newwidth,$newheight);  
        imagecopyresized($newdim,$modifiedimage,0,0,0,0,$newwidth,$newheight,$width,$height);  
        imagejpeg($modifiedimage,$newname,60);  

        // Remove temp images  
        imagedestroy($modifiedimage);  
        imagedestroy($newdim);  
    } else {  
        // Just add picture to folder without resize (if org dim < max dim)  
        $newwidth = $width;  
        $newheight = $height;  
        $copied = copy($_FILES['file']['tmp_name'], $newname);  
    }

    //Add image information to the MySQL database  
    mysql_query("SET character_set_connection=utf8", $dbh);  
    mysql_query("INSERT INTO userpictures (PicId, Picext, UserId, Width, Height, Size) VALUES('$imagenumber', '$extension', '$_SESSION[userid]', '$newwidth', '$newheight', $size)") 

【问题讨论】:

  • @Hans:请为 markdown 解析器标记代码块,例如通过选择文本然后按 ctrl+k (这会将文本缩进四个空格,然后将其解析为“代码块”)

标签: php image resize


【解决方案1】:

您是否检查过实际使用了图像大小调整块?还要考虑那里的一些调试输出。我看不出有什么明显的错误

if ($width > $maxWidth || etc...) {
   echo "Hey, gotta shrink that there image";
   ... do the resizing ...
   $resizedImage = getimagesize($newname);
   var_dump($resizedImage); // see if the new image actually exists/what its stats are
   etc....
} else {
   echo "Woah, that's a small picture, I'll just make a straight copy instead";
}

您可能还想将 $newheight/$newwidth 舍入为整数值 - 在几乎所有情况下,您都会得到一些小数结果,并且图像没有小数像素。

顺便说一句,您的 ID 号生成器存在竞争条件:

$query = mysql_query("SELECT MAX(PicId) AS number FROM userpictures");  
$row = mysql_fetch_array($query);  
$imagenumber = $row['number']+1; 

考虑两个上传几乎同时完成的情况。他们都将获得相同的 ID 号(例如,25)。然后,处理时间较长的上传将“获胜”并覆盖更快的上传。

考虑使用以下逻辑重写数据库部分以使用事务:

 1. start transaction
 2. insert skeleton record into the db and get its ID
 3. do image processing, copying, saving, etc...
 4. update record with the new image's stats
 5. commit the transaction

这样,事务将“隐藏”记录,因为它尚未提交,两个或多个同时上传无法获得相同的 ID 号,并且如果在图像处理过程中出现任何故障(内存、磁盘空间不足、损坏的源图像等...)您只需回滚事务并清理混乱即可。

【讨论】:

  • vardump 显示新图像尚未调整大小。也感谢您对“比赛条件”的评论!
【解决方案2】:

乍一看,我看不出脚本有什么问题,但如果没有一些测试输出和错误报告,这很难解决。

  1. 出现error_reporting(E_ALL)

  2. 查看$newname 设置为什么

  3. 查看 copy() 命令的作用

我敢打赌,当您打开错误报告时,您会得到一些东西。 顺便说一下,要找出文件的扩展名,我会使用pathinfo

【讨论】:

  • 当错误报告 = 未显示错误有关参数的信息:577.880859375(所需内存)300-20($width - $newwidth)263-17.533333333333($height - $newheight)UserPics/25.jpg ($newname)
  • 奇怪。 @Hans 如果您将imagejpeg 直接输出到浏览器(添加content-typeheader)会发生什么?你得到调整大小的图像吗?
【解决方案3】:

1) 检查权限。确保您的 UserPics 目录可以由运行 Web 进程的用户编写(例如,debian 系统上的 www-data)。对于这类事情,我不熟悉 Windows 上的系统权限,但如果我自己写这篇文章,我会检查一下(我有,而且我可能做过)。

2) 本身不相关,但请查看http://sourceforge.net/projects/littleutils/

我在所有上传的图像上运行 opt-gif 和 opt-jpg 以无损地节省磁盘空间(我的应用不需要丢失的内容)

【讨论】:

    猜你喜欢
    • 2017-11-03
    • 1970-01-01
    • 1970-01-01
    • 2012-08-01
    • 1970-01-01
    • 2011-08-25
    • 2014-08-26
    • 2011-05-28
    • 1970-01-01
    相关资源
    最近更新 更多