2017-04-17 1 views
1

私は、ユーザーがアップロードした画像を受け入れ、最大幅/高さが4,000pxになるように比例してサイズを変更し、400pxおよび800pxのサムネイルを生成する機能を持っています。透明なPNGを処理し、白い背景を適用する能力が必要です。PHP GDサイズ変更でアーティファクトが発生する

私の現在のコードはこれをすべて行いますが、JPEGに特有の望ましくないアーチファクトを追加します。それらは垂直線であり、クローズアップされたときに非常に洗い流されたバーコードのように見えます(400%Zoomed Screenshot添付)。これは、拡大縮小されているサイズでアップロードされたときに元の画像にも発生します。透明なPNGではさらに普及しているようですが、JPEGの白い領域でも同様に起こります。 JPEGファイルは、(Windows上でUbuntuの下ではなく、PHP 7.0.1の下でPHP 7.1.3で発生した)私は問題が環境に固有であると結論品質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', '[email protected]', $path), 80); 
     } 
    } 

    return $dst; 
} 
+1

私は 'imagecopyresampled'の代わりに' imagecopyresized'を使ってみてみたいと思います - おそらくこれもまた助けになりますhttp://stackoverflow.com/questions/23200823/gd-quality-issue-with-transparent -pngs || http://stackoverflow.com/questions/23993901/imagecopyresampled-introduces-artifacts-in-transparent-png –

+0

うーん、良い考え方、「imagecopyresized」はうまくいくと思います。私はこの症状がUbuntuのPHP 7.1.3では発生しているが、開発中のWindowsではPHP 7.0.1では発生していないことに気付きました。たぶん、設定関連? –

答えて

0

と一緒に保存されています。 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()setImageCompressionQuality、及びstripImage()への呼び出しを組み合わせfilesizes 53%の減少をもたらしました。 (Source

関連する問題