图片调整大小错误
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 的高度以上是关于图片调整大小错误的主要内容,如果未能解决你的问题,请参考以下文章