PHP GD Resizing导致工件

时间:2017-04-17 16:22:23

标签: php image gd

我有一个功能,我用来接受用户上传的图像,按比例将其缩放到最大宽度/高度为4,000px,并生成400px和800px缩略图。它需要能够处理透明的PNG并应用白色背景。

我当前的代码完成了所有这些操作,然而,它增加了不典型的JPEG图像。它们是垂直条纹,当近距离观察时看起来像一个非常褪色的条形码(附加400%Zoomed截图)。当按照缩放到的尺寸上传时,这甚至会出现在原始图像上。它似乎在透明PNG中更为普遍,但也出现在JPEG的白色区域。 JPEG正在使用Quality 80保存。

400% Zoom of Originally All-White Area

function resize_image($file, $w, $h, $strict = false, $crop = false, $path = null, $thumbnail = false)
{
    // Check for Valid Image + Calculate Ratio
    list($width, $height) = getimagesize($file);

    if (empty($width) || empty($height))
    {
        echo json_encode(['result' => 'error', 'error' => 'file_format_invalid']);
        http_response_code(405);
        exit;
    }

    $r = $width / $height;

    if (!$strict)
    {
        $w = min($w, $width);
        $h = min($h, $height);
    }

    $wTa = min($w, 400);
    $hTa = min($h, 400);

    $wTb = min($w, 800);
    $hTb = min($h, 800);

    // Apply Crop Constraint
    if ($crop)
    {
        if ($width > $height)
        {
            $width = ceil($width - ($width * abs($r - $w / $h)));
            $widthTa = ceil($width - ($width * abs($r - $wTa / $hTa)));
            $widthTb = ceil($width - ($width * abs($r - $wTb / $hTb)));
        }

        else
        {
            $height = ceil($height - ($height * abs($r - $w / $h)));
            $heightTa = ceil($height - ($height * abs($r - $wTa / $hTa)));
            $heightTb = ceil($height - ($height * abs($r - $wTa / $hTb)));
        }

        $newWidth = $w;
        $newHeight = $h;
    }

    else
    {
        if ($w / $h > $r || $r < 1)
        {
            $newWidth = $h * $r;
            $newWidthTa = $hTa * $r;
            $newWidthTb = $hTb * $r;

            $newHeight = $h;
            $newHeightTa = $hTa;
            $newHeightTb = $hTb;
        }

        else
        {
            $newHeight = $w / $r;
            $newHeightTa = $wTa / $r;
            $newHeightTb = $wTb / $r;

            $newWidth = $w;
            $newWidthTa = $wTa;
            $newWidthTb = $wTb;
        }
    }

    // Create, Resample + Return Image
    $src = imagecreatefromstring(file_get_contents($file));
    $dst = imagecreatetruecolor($newWidth, $newHeight);
    $fff = imagecolorallocate($dst, 255, 255, 255);

    imagefill($dst, 0, 0, $fff);
    imagecopyresampled($dst, $src, 0, 0, 0, 0, $newWidth, $newHeight, $width, $height);

    if (!is_null($path))
    {
        imagejpeg($dst, $path, 80);

        if ($thumbnail)
        {
            $dstThumbA = imagecreatetruecolor($newWidthTa, $newHeightTa);
            $dstThumbB = imagecreatetruecolor($newWidthTb, $newHeightTb);

            $fffThumbA = imagecolorallocate($dstThumbA, 255, 255, 255);
            $fffThumbB = imagecolorallocate($dstThumbB, 255, 255, 255);

            imagefill($dstThumbA, 0, 0, $fffThumbA);
            imagefill($dstThumbB, 0, 0, $fffThumbB);

            imagecopyresampled($dstThumbA, $src, 0, 0, 0, 0, $newWidthTa, $newHeightTa, $width, $height);
            imagecopyresampled($dstThumbB, $src, 0, 0, 0, 0, $newWidthTb, $newHeightTb, $width, $height);

            imagejpeg($dstThumbA, str_replace('.jpg', '-thumb.jpg', $path), 80);
            imagejpeg($dstThumbB, str_replace('.jpg', '-thumb@2x.jpg', $path), 80);
        }
    }

    return $dst;
}

1 个答案:

答案 0 :(得分:0)

我得出结论,该问题是针对环境的(在Ubuntu下的PHP 7.1.3上发生,但在Windows上不在PHP 7.0.1下发生)。重新安装php7.1php7.1-gd无效。

最终我决定咬紧牙关并使用ImageMagick重写,从而产生更简洁的代码块:

$magickSource = new Imagick();
$magickSource->readImageBlob(file_get_contents($file));
$magickSource = $magickSource->flattenImages();

$magickFull = clone $magickSource;
$magickFull->resizeImage(min($originalWidth, $newWidth), min($originalHeight, $newHeight), Imagick::FILTER_LANCZOS, 1, true);
$magickFull->setImageCompression(Imagick::COMPRESSION_JPEG);
$magickFull->setImageCompressionQuality(75);
$magickFull->stripImage();
$magickFull->writeImage($path);
$magickFull->destroy();

if ($thumbnail)
{
    $magickThumb = clone $magickSource;
    $magickThumb->resizeImage(min($originalWidth, 400), min($originalHeight, 400), Imagick::FILTER_LANCZOS, 1, true);
    $magickThumb->setImageCompression(Imagick::COMPRESSION_JPEG);
    $magickThumb->setImageCompressionQuality(75);
    $magickThumb->stripImage();
    $magickThumb->writeImage(str_replace('.jpg', '-thumb.jpg', $path));
    $magickThumb->destroy();
}

setImageCompression()setImageCompressionQualitystripImage()的调用使合并文件大小减少了53%。 ({{3}})