图片调整大小错误

Posted

技术标签:

【中文标题】图片调整大小错误【英文标题】:Image resize bug 【发布时间】:2014-10-10 14:02:24 【问题描述】:

我继承了一个调整图像大小的函数。它在大多数情况下运行良好,但由于某种原因,在某些情况下调整图像大小的结果与最初包含的图像完全不同。函数如下:

function image_resize($source, $destination, $width, $height, $resizeMode='fit', $type = 'jpeg', $options = array()) 


    $defaults = array(
        'output' => 'file',
        'isFile' => true,
        'quality' => '100',
        'preserveAnimation' => false,
        'offsetTop' => 0,
        'offsetLeft' => 0,
        'offsetType' => 'percent'
    );

    foreach ($defaults as $k => $v) 
        if (!isset($options[$k])) 
            $options[$k] = $v;
        
    

    if ($options['isFile']) 
        $image_info = getimagesize($source);
        $image = null;
        switch ($image_info[2]) 
            case IMAGETYPE_JPEG:
                $image = imagecreatefromjpeg($source);
                break;
            case IMAGETYPE_PNG:
                $image = imagecreatefrompng($source);
                break;
            case IMAGETYPE_GIF:
                $image = imagecreatefromgif($source);
                break;
            case IMAGETYPE_BMP:
                $image = imagecreatefromwbmp($source);
                break;
            default :
                return false;
        
     else 
        $image = imagecreatefromstring($source);
    

    //we have an image resource
    $iwidth = imagesx($image);
    $iheight = imagesy($image);

    //We need $width and $height for this call
    if (QM::isAcceptableProfilePhotoSize($width, $height) == false)
    
        throw new Exception("Size of ".$width."x".$height." is not supported");
    

    //determine ratios
    $wratio = $width / $iwidth;
    $hratio = $height / $iheight;
    $mratio = min(array($wratio, $hratio));

    $rimage = null;

    switch ($resizeMode) 
        case 'fit':
            $rimage = imagecreatetruecolor($iwidth * $mratio, $iheight * $mratio);
            $image = imagecopyresampled($rimage, $image, 0, 0, 0, 0, $iwidth * $mratio, $iheight * $mratio, $iwidth, $iheight);
            break;
        case 'crop':
            $rratio = $width / $height;


            if ($rratio < 1) 
                $nwidth = $iwidth;
                $nheight = $iwidth * 1/$rratio;
                if ($nheight>$iheight) 
                    $nwidth = $nwidth*$iheight/$nheight;
                    $nheight = $iheight;
                
             else 
                $nwidth = $iheight*$rratio;
                $nheight = $iheight;
                if ($nwidth>$iwidth) 
                    $nheight = $nheight*$iwidth/$nwidth;
                    $nwidth = $iwidth;
                
            
            switch ($options['offsetType']) 
                case 'percent':
                    $sx = ($iwidth-$nwidth)*$options['offsetLeft']/100;
                    $sy = ($iheight-$nheight)*$options['offsetTop']/100;
                    break;
                default :
                    return false;
            

            $rimage = imagecreatetruecolor($width, $height);
            $image = imagecopyresampled($rimage, $image, 0, 0, $sx, $sy, $width, $height, $nwidth, $nheight);
            break;
        default :
            return false;
            break;
    

    if (!is_writeable(dirname($destination))) 
        throw new Exception(getcwd(). "/" .dirname($destination)." is not writeable");
    

    switch ($options['output']) 
        case 'file':
            switch ($image_info[2]) 
                case IMAGETYPE_JPEG:
                    return imagejpeg($rimage, $destination, $options['quality']);
                case IMAGETYPE_PNG:
                    return imagepng($rimage, $destination, 0);
                case IMAGETYPE_GIF:
                    return imagegif($rimage, $destination);
                case IMAGETYPE_BMP:
                    return imagejpeg($rimage, $destination, $options['quality']);
                default :
                    return false;
                    break;
            
            return true;
            break;
        default :
            return false;
            break;
    

导致问题的示例图像:

这张图片上传成功,但是当我尝试调整它的大小时,生成的图片是:

我这样调用函数:

image_resize($ofile, $cfile, $width, $height, 'crop', 'jpeg');

其中$ofile 是原始文件,$cfile 是计划目标,$width 是所需宽度(本例中为 90),$height 是所需高度(本例中为 90),@987654331 @ 是选择的策略,'jpeg' 是某个$type 值,在函数中没有用到(我已经提到,我继承了代码)。另外,可以重现问题的唯一示例是附加图像,这是一个png,其他png文件已正确上传,所以我不明白问题的原因,也不知道如何解决。任何人都可以描述问题的原因吗?我已经搜索和试验了很长时间,但没有成功。

【问题讨论】:

***.com/questions/24430176/… 可能与透明度有关***.com/questions/279236/…? 【参考方案1】:

我用你的鸟图片尝试了你的“image_resize”功能,它在我的电脑上运行得很好, 无论我将源图像设置为 jpg 还是 png,它都能按预期工作:

但是为什么不选择“适合”而不是像这样选择“裁剪”:

image_resize($ofile, $cfile, $width = 90, $height = 90, 'fit', 'jpeg');

编辑:基于其他人在调整 PNG 大小后得到黑色图像的问题,这将是更正:

function image_resize($source, $destination, $width, $height, $resizeMode='fit', $type = 'jpeg', $options = array()) 

    $defaults = array(
        'output' => 'file',
        'isFile' => true,
        'quality' => '100',
        'preserveAnimation' => false,
        'offsetTop' => 0,
        'offsetLeft' => 0,
        'offsetType' => 'percent'
    );

    foreach ($defaults as $k => $v) 
        if (!isset($options[$k])) 
            $options[$k] = $v;
        
    

    if ($options['isFile']) 
        $image_info = getimagesize($source);
        $image = null;
        switch ($image_info[2]) 
            case IMAGETYPE_JPEG:
                $image = imagecreatefromjpeg($source);
                break;
            case IMAGETYPE_PNG:
                $image = imagecreatefrompng($source);
                break;
            case IMAGETYPE_GIF:
                $image = imagecreatefromgif($source);
                break;
            case IMAGETYPE_BMP:
                $image = imagecreatefromwbmp($source);
                break;
            default :
                return false;
           
     else 
        $image = imagecreatefromstring($source);
       

    //we have an image resource
    $iwidth = imagesx($image);
    $iheight = imagesy($image);

    //determine ratios
    $wratio = $width / $iwidth;
    $hratio = $height / $iheight;
    $mratio = min(array($wratio, $hratio));

    $rimage = null;

    switch ($resizeMode) 
        case 'fit':
            $rimage = imagecreatetruecolor($iwidth * $mratio, $iheight * $mratio);
            imagealphablending( $rimage, false );
            imagesavealpha( $rimage, true ); 
            $image = imagecopyresampled($rimage, $image, 0, 0, 0, 0, $iwidth * $mratio, $iheight * $mratio, $iwidth, $iheight);
            break;
        case 'crop':
            $rratio = $width / $height;


            if ($rratio < 1) 
                $nwidth = $iwidth;
                $nheight = $iwidth * 1/$rratio;
                if ($nheight>$iheight) 
                    $nwidth = $nwidth*$iheight/$nheight;
                    $nheight = $iheight;
                
             else 
                $nwidth = $iheight*$rratio;
                $nheight = $iheight;
                if ($nwidth>$iwidth) 
                    $nheight = $nheight*$iwidth/$nwidth;
                    $nwidth = $iwidth;
                
            
            switch ($options['offsetType']) 
                case 'percent':
                    $sx = ($iwidth-$nwidth)*$options['offsetLeft']/100;
                    $sy = ($iheight-$nheight)*$options['offsetTop']/100;
                    break;
                default :
                    return false;
            

            $rimage = imagecreatetruecolor($width, $height);
            imagealphablending( $rimage, false );
            imagesavealpha( $rimage, true );
            $image = imagecopyresampled($rimage, $image, 0, 0, $sx, $sy, $width, $height, $nwidth, $nheight);
            break;
        default :
            return false;
            break;
    

    if (!is_writeable(dirname($destination))) 
        throw new Exception(getcwd(). "/" .dirname($destination)." is not writeable");
    

    switch ($options['output']) 
        case 'file':
            switch ($image_info[2]) 
                case IMAGETYPE_JPEG:
                    return imagejpeg($rimage, $destination, $options['quality']);
                case IMAGETYPE_PNG:
                    return imagepng($rimage, $destination, 0);
                case IMAGETYPE_GIF:
                    return imagegif($rimage, $destination);
                case IMAGETYPE_BMP:
                    return imagejpeg($rimage, $destination, $options['quality']);
                default :
                    return false;
                    break;
            
            return true;
            break;
        default :
            return false;
            break;
    

【讨论】:

'fit' 使图片变形。选择“crop”是有原因的。您是否使用“crop”成功运行它? 是的,“crop”参数没有问题。 (但它在右边缘裁剪了鸟的尾巴,这就是为什么我更喜欢“适合”,而且我不会得到变形的图片,image_resize 会自动计算正确的宽/高比) 变形是指宽高比变形。自然,这张图片的宽度大于它的高度,因此通过使它们相等,我们使它的宽度变薄,因此我们正在变形图片。裁剪可以保持图片的正确外观,但存在裁剪部分的问题。我宁愿选择切割版本而不是变形版本。关键是这个在多台计算机上裁剪的代码会生成黑色图像,这就是问题所在。如果您无法重现它,那么您可能无法提供帮助。 因此,“适合”不是一个选项。我相信您由于某种原因无法重现它,但这里的问题每次都存在。如果您能在我的最后找出导致问题的原因,那么我自然会赞成并接受您的回答。 是的,如果图像缩放到 90 x 90,它会变形。但是这里的“fit”参数可以防止这种情况发生。比率由函数 image_resizeso() 自动计算,因此尺寸将被强制为更小的缩放图像 90 x 64。示例:$iwidth = 1622; $i 高度 = 1150; $宽度 = 90; $高度 = 90; $比率 = 90/1622; $mratio = 90/1150; $mratio = 90/1622;然后你得到 1622 x (90/1622) = 90 的宽度和 1150 x (90/1622) = 64 的高度

以上是关于图片调整大小错误的主要内容,如果未能解决你的问题,请参考以下文章

在 Xcode 中调整窗格大小

QT中怎么调整显示图片大小

如何批量调整Word中图片大小

IOS开发中如何调整WKWebView中的图片大小

wps图片批量调整大小

word如何一键调整全部图片大小?