2014-04-25 2 views
0

다음과 같은 PHP 스크립트를 사용하여 기존 jpeg 이미지를 가져 와서 더 작은 축소판으로 크기를 조정하고 png 워터 마크를 추가합니다. 내가 가지고있는 문제는 GD 라이브러리를 사용하여 줄이면 출력 축소가 너무 작아집니다 (크기 축소가 필요하지 않을 때 훨씬 더 선명합니다. 즉, 원본 크기와 출력 크기가 동일한 경우). gd에서 크기 조정 알고리즘이 좋지 않다고 말했고 대신 adaptive-resize 옵션을 사용하여 ImageMagick을 사용하는 것이 좋습니다. 기본적으로 내가 대신 GD 라이브러리 (바이 큐빅 선명와) ImageMagick를 사용하도록 스크립트를 변환 할 : 위의GD 이미지 리사이저를 바이 큐빅 샤퍼와 동등한 ImageMagick으로 변환

<?php 

if (isset($_GET['image']) && isset($_GET['width'])) { 
$image = $_GET['image']; 
$max_width = $_GET['width']; 
$max_height = 800; 
$wmark='watermark.png'; 
$wmarks='watermark_s.png'; 
$wmarkm='watermark_m.png'; 
$wmarkno='nowatermark.png'; 
$noimg='noimg.png'; 
if (file_exists($image)) { 

    $cached='cache/'.preg_replace('/(\.\w+$)/',".{$max_width}\\1",$image); 

    if (file_exists($cached)) { 
    $cst=stat($cached); 
    $fst=stat($image); 
    if ($fst[9]<=$cst[9] && $fst[10]<=$cst[10]) { 
     if (isset($_SERVER['HTTP_IF_MODIFIED_SINCE']) && strtotime($_SERVER['HTTP_IF_MODIFIED_SINCE'])>=$cst[9]) { 
     header("HTTP/1.0 304 Not Modified"); 
    } else { 
header('Content-type: image/jpeg'); 
header('Last-Modified: '.gmdate('D, d M Y H:i:s',$cst[9]).' GMT'); 
header('Cache-Control: private'); 
print file_get_contents($cached); 
     } 
     exit; 
    } 
    } 

$size = GetImageSize($image); 
$watermark_img = imagecreatefrompng($wmark); 
$watermarks_img = imagecreatefrompng($wmarks); 
$watermarkm_img = imagecreatefrompng($wmarkm); 
$watermarkno_img = imagecreatefrompng($wmarkno); 

$wmrk_size = getimagesize($wmark); 
$wmrks_size = getimagesize($wmarks); 
$wmrkm_size = getimagesize($wmarkm); 
$wmrkno_size = getimagesize($wmarkno); 


$width = $size[0]; 
$height = $size[1]; 

@$x_ratio = $max_width/$width; 
@$y_ratio = $max_height/$height; 

if (($width <= $max_width) && ($height <= $max_height)) 
{ 
    $tn_height = $height; 
    $tn_width = $width; 
} 
else if (($x_ratio * $height) < $max_height) 
{ 
    $tn_height = ceil($x_ratio * $height); 
    $tn_width = $max_width; 
} 
else 
{ 
    $tn_height = $max_height; 
    $tn_width = ceil($y_ratio * $width); 
} 

if ((($tn_width) <>0) && (($tn_height)<>0)) { 



$src = ImageCreateFromJPEG($image); 
$dst = ImageCreateTrueColor($tn_width, $tn_height); 
ImageCopyResampled($dst, $src, 0, 0, 0, 0, $tn_width, $tn_height, $width, $height); 
//$dst = imagecreatefromjpeg($dst); 
if (ImageSX($dst) > 300) { 
    $posx = (ImageSX($dst) - ImageSX($watermark_img))/2; 
    $posy = (ImageSY($dst) - ImageSY($watermark_img))/2; 
imagecopy($dst, $watermark_img, $posx, $posy, 0, 0, $wmrk_size[0], $wmrk_size[1]); 
} else { 
$posxs = (ImageSX($dst) - ImageSX($watermarkno_img))/2; 
$posys = (ImageSY($dst) - ImageSY($watermarkno_img))/2; 
imagecopy($dst, $watermarkno_img, $posxs, $posys, 0, 0, $wmrkno_size[0], $wmrkno_size[1]); 
} 
header('Content-type: image/jpeg'); 
header('Last-Modified: '.gmdate('D, d M Y H:i:s').' GMT'); 
header('Cache-Control: private'); 
ImageJPEG($dst, null, 90); 
ImageJPEG($dst, $cached, 90); 
ImageDestroy($src); 
ImageDestroy($dst); 
                } 

        } 
    } 
?> 

답변

1

ImageMagick을 사용하여 직접 수정했습니다. GD보다 훨씬 선명하고 좋은 결과물. 다음은 수정 된 버전입니다. 희망이 다른 사람들을 도울 수 있습니다.

<?php 
if (isset($_GET['image']) && isset($_GET['width']) && is_numeric($_GET['width'])) { 
// Get image name 
    $original_image = $_GET['image']; 
    // Watermarks 
    $wmark='watermark.png'; //largest watermark 
    $wmarkm='watermark_m.png'; //medium watermark 
    $wmarks='watermark_s.png'; //smallest watermark 
    $wmarkno='nowatermark.png'; //No watermark 

// Maximum image width 
    $max_width = (int)$_GET['width']; 
// Maximum image height 
    $max_height = "800"; 

    if (file_exists($original_image)) { 
    $cached='cache/'.preg_replace('/(\.\w+$)/',".{$max_width}\\1",$original_image); 

    if (file_exists($cached)) { 
    $cst=stat($cached); 
    $fst=stat($original_image); 
    if ($fst[9]<=$cst[9] && $fst[10]<=$cst[10]) { 
     if (isset($_SERVER['HTTP_IF_MODIFIED_SINCE']) && strtotime($_SERVER['HTTP_IF_MODIFIED_SINCE'])>=$cst[9]) { 
     header('Last-Modified: '.gmdate('D, d M Y H:i:s', filemtime($cached)).' GMT', true, 304); 
     } else { 
    header('Content-type: image/jpeg'); 
    header('Last-Modified: '.gmdate('D, d M Y H:i:s',$cst[9]).' GMT'); 
    header('Cache-Control: private'); 
    readfile($cached); 
     } 
     exit; 
    } 
    } 

    if ($max_width > 300) { 
    $watermark=$wmark; 
    } elseif ($max_width > 152 && $max_width < 300) { 
     $watermark=$wmarkm; 
    }elseif ($max_width > 50 && $max_width < 151){ 
     $watermark=$wmarks; 
    } else { 
     $watermark=$wmarkno; 
    } 

// Resize the image, save and output to browser with headers 
    exec("convert -filter Lanczos $original_image -thumbnail {$max_width}x{$max_height} -quality 90 {$watermark} -gravity center -unsharp 2x0.5+0.2+0 -composite {$cached}"); 
    header('Content-type: image/jpeg'); 
    header('Last-Modified: '.gmdate('D, d M Y H:i:s').' GMT'); 
    header('Cache-Control: private'); 
    readfile($cached); 
} 
} 
?> 

편집

은 일괄 크기 조정을하고 있었던 것처럼 ImageMagick이, 내 서버에 과도한 자원을 사용하고 있었던 것으로 보인다. 결국 GraphicsMagick으로 전환하기로 결정했습니다. 동일한 이미지 크기를 출력하면서 거의 동일한 파일 크기로 출력하고, 서버에서 훨씬 적은 리소스를 사용하여 훨씬 빨라졌습니다.

이를 위해, 난 그냥 GraphicsMagick를 설치에서 간부 라인을 변경 : 원하는 사람을 위해,

//create the resized image 
    exec("gm convert -filter Lanczos {$original_image} -thumbnail {$max_width}x{$max_height} -quality 90 -unsharp 2x0.5+0.2+0 {$cached}"); 
    //apply the watermark and recreate the watermarked image, overwriting the previously resized image 
    exec("gm composite -quality 90 -dissolve 100 -gravity center {$watermark} {$cached} {$cached}"); 

편집 2

또 다른 방법 :

exec("convert -filter Lanczos $original_image -thumbnail {$max_width}x{$max_height} -quality 90 {$watermark} -gravity center -unsharp 2x0.5+0.2+0 -composite {$cached}"); 

으로 또는 GD로 계속 작업해야하는 경우, 다음과 같은 우수한 언샵 마스크 기능 (http://vikjavev.no/computing/ump.php에서 가져옴)을 사용하는 것입니다.

<?php 

/* 

New: 
- In version 2.1 (February 26 2007) Tom Bishop has done some important speed enhancements. 
- From version 2 (July 17 2006) the script uses the imageconvolution function in PHP 
version >= 5.1, which improves the performance considerably. 


Unsharp masking is a traditional darkroom technique that has proven very suitable for 
digital imaging. The principle of unsharp masking is to create a blurred copy of the image 
and compare it to the underlying original. The difference in colour values 
between the two images is greatest for the pixels near sharp edges. When this 
difference is subtracted from the original image, the edges will be 
accentuated. 

The Amount parameter simply says how much of the effect you want. 100 is 'normal'. 
Radius is the radius of the blurring circle of the mask. 'Threshold' is the least 
difference in colour values that is allowed between the original and the mask. In practice 
this means that low-contrast areas of the picture are left unrendered whereas edges 
are treated normally. This is good for pictures of e.g. skin or blue skies. 

Any suggenstions for improvement of the algorithm, expecially regarding the speed 
and the roundoff errors in the Gaussian blur process, are welcome. 

*/ 

function UnsharpMask($img, $amount, $radius, $threshold) { 

//////////////////////////////////////////////////////////////////////////////////////////////// 
//// 
////     Unsharp Mask for PHP - version 2.1.1 
//// 
//// Unsharp mask algorithm by Torstein H?nsi 2003-07. 
////    thoensi_at_netcom_dot_no. 
////    Please leave this notice. 
//// 
/////////////////////////////////////////////////////////////////////////////////////////////// 



    // $img is an image that is already created within php using 
    // imgcreatetruecolor. No url! $img must be a truecolor image. 

    // Attempt to calibrate the parameters to Photoshop: 
    if ($amount > 500) $amount = 500; 
    $amount = $amount * 0.016; 
    if ($radius > 50) $radius = 50; 
    $radius = $radius * 2; 
    if ($threshold > 255) $threshold = 255; 

    $radius = abs(round($radius));  // Only integers make sense. 
    if ($radius == 0) { 
     return $img; imagedestroy($img); break;  } 
    $w = imagesx($img); $h = imagesy($img); 
    $imgCanvas = imagecreatetruecolor($w, $h); 
    $imgBlur = imagecreatetruecolor($w, $h); 


    // Gaussian blur matrix: 
    //       
    // 1 2 1   
    // 2 4 2   
    // 1 2 1   
    //       
    ////////////////////////////////////////////////// 


    if (function_exists('imageconvolution')) { // PHP >= 5.1 
      $matrix = array( 
      array(1, 2, 1), 
      array(2, 4, 2), 
      array(1, 2, 1) 
     ); 
     imagecopy ($imgBlur, $img, 0, 0, 0, 0, $w, $h); 
     imageconvolution($imgBlur, $matrix, 16, 0); 
    } 
    else { 

    // Move copies of the image around one pixel at the time and merge them with weight 
    // according to the matrix. The same matrix is simply repeated for higher radii. 
     for ($i = 0; $i < $radius; $i++) { 
      imagecopy ($imgBlur, $img, 0, 0, 1, 0, $w - 1, $h); // left 
      imagecopymerge ($imgBlur, $img, 1, 0, 0, 0, $w, $h, 50); // right 
      imagecopymerge ($imgBlur, $img, 0, 0, 0, 0, $w, $h, 50); // center 
      imagecopy ($imgCanvas, $imgBlur, 0, 0, 0, 0, $w, $h); 

      imagecopymerge ($imgBlur, $imgCanvas, 0, 0, 0, 1, $w, $h - 1, 33.33333); // up 
      imagecopymerge ($imgBlur, $imgCanvas, 0, 1, 0, 0, $w, $h, 25); // down 
     } 
    } 

    if($threshold>0){ 
     // Calculate the difference between the blurred pixels and the original 
     // and set the pixels 
     for ($x = 0; $x < $w-1; $x++) { // each row 
      for ($y = 0; $y < $h; $y++) { // each pixel 

       $rgbOrig = ImageColorAt($img, $x, $y); 
       $rOrig = (($rgbOrig >> 16) & 0xFF); 
       $gOrig = (($rgbOrig >> 8) & 0xFF); 
       $bOrig = ($rgbOrig & 0xFF); 

       $rgbBlur = ImageColorAt($imgBlur, $x, $y); 

       $rBlur = (($rgbBlur >> 16) & 0xFF); 
       $gBlur = (($rgbBlur >> 8) & 0xFF); 
       $bBlur = ($rgbBlur & 0xFF); 

       // When the masked pixels differ less from the original 
       // than the threshold specifies, they are set to their original value. 
       $rNew = (abs($rOrig - $rBlur) >= $threshold) 
        ? max(0, min(255, ($amount * ($rOrig - $rBlur)) + $rOrig)) 
        : $rOrig; 
       $gNew = (abs($gOrig - $gBlur) >= $threshold) 
        ? max(0, min(255, ($amount * ($gOrig - $gBlur)) + $gOrig)) 
        : $gOrig; 
       $bNew = (abs($bOrig - $bBlur) >= $threshold) 
        ? max(0, min(255, ($amount * ($bOrig - $bBlur)) + $bOrig)) 
        : $bOrig; 



       if (($rOrig != $rNew) || ($gOrig != $gNew) || ($bOrig != $bNew)) { 
         $pixCol = ImageColorAllocate($img, $rNew, $gNew, $bNew); 
         ImageSetPixel($img, $x, $y, $pixCol); 
        } 
      } 
     } 
    } 
    else{ 
     for ($x = 0; $x < $w; $x++) { // each row 
      for ($y = 0; $y < $h; $y++) { // each pixel 
       $rgbOrig = ImageColorAt($img, $x, $y); 
       $rOrig = (($rgbOrig >> 16) & 0xFF); 
       $gOrig = (($rgbOrig >> 8) & 0xFF); 
       $bOrig = ($rgbOrig & 0xFF); 

       $rgbBlur = ImageColorAt($imgBlur, $x, $y); 

       $rBlur = (($rgbBlur >> 16) & 0xFF); 
       $gBlur = (($rgbBlur >> 8) & 0xFF); 
       $bBlur = ($rgbBlur & 0xFF); 

       $rNew = ($amount * ($rOrig - $rBlur)) + $rOrig; 
        if($rNew>255){$rNew=255;} 
        elseif($rNew<0){$rNew=0;} 
       $gNew = ($amount * ($gOrig - $gBlur)) + $gOrig; 
        if($gNew>255){$gNew=255;} 
        elseif($gNew<0){$gNew=0;} 
       $bNew = ($amount * ($bOrig - $bBlur)) + $bOrig; 
        if($bNew>255){$bNew=255;} 
        elseif($bNew<0){$bNew=0;} 
       $rgbNew = ($rNew << 16) + ($gNew <<8) + $bNew; 
        ImageSetPixel($img, $x, $y, $rgbNew); 
      } 
     } 
    } 
    imagedestroy($imgCanvas); 
    imagedestroy($imgBlur); 

    return $img; 

} 
?> 
0

PHP 5.5은 보간 방법을 변경할 수 문서화되지 않은 기능을 imagesetinterpolation()가 있습니다. 소스 코드에서만 보았습니다. 나 자신을 결코 시도하지 않았다. 귀하의 마일리지는 다를 수 있습니다.

이 함수는 이미지 리소스와 다음 상수 중 하나의 매개 변수를 사용합니다.

IMG_BELL 
IMG_BESSEL 
IMG_BILINEAR_FIXED 
IMG_BICUBIC 
IMG_BICUBIC_FIXED 
IMG_BLACKMAN 
IMG_BOX 
IMG_BSPLINE 
IMG_CATMULLROM 
IMG_GAUSSIAN 
IMG_GENERALIZED_CUBIC 
IMG_HERMITE 
IMG_HAMMING 
IMG_HANNING 
IMG_MITCHELL 
IMG_POWER 
IMG_QUADRATIC 
IMG_SINC 
IMG_NEAREST_NEIGHBOUR 
IMG_WEIGHTED4 
IMG_TRIANGLE 

IMG_BILINEAR_FIXED가 기본값입니다.

+0

감사! 나는 PHP 5.4 atm tho에있다. 내년에 5.5 버전으로 업그레이드 할 예정이며, 아직까지는 원래의 게시물에 대한 해결책이 필요합니다. 건배. – CreativeMind

+0

p.s. 또한 목록에있는 보간 중 어느 것이 bicubic-sharper (bicubic은 부드럽고 예리함 등을 의미 할 수 있음)에 상응하는지 알 수 없습니다. 건배. – CreativeMind

관련 문제