使用双三次锐化器将GD图像大小调整器转换为等效的ImageMagick

尼基塔

我有以下PHP脚本,可使用现有的jpeg图像并将其调整为较小的缩略图,同时向其添加png水印。我遇到的问题是,还原是通过GD库完成的,这会使输出拇指在缩小后不那么尖锐(当不需要减小尺寸时,即输出和原来的尺寸相同时,它会变得更加尖锐)。有人告诉我gd中的大小调整算法不是很好,建议改用ImageMagick,并使用adaptive-resize选项。我基本上想将脚本转换为使用ImageMagick(具有双三次锐度)而不是GD库:

<?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);
                                                   }

                     }
  }
?>
尼基塔

我已经使用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并将exec行更改为:

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}"); 

到:

  //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

对于任何想要或需要继续使用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;  

} 
?>

本文收集自互联网,转载请注明来源。

如有侵权,请联系[email protected] 删除。

编辑于
0

我来说两句

0条评论
登录后参与评论

相关文章

来自分类Dev

使用wxPython在框内嵌套大小调整器

来自分类Dev

如何在PHP中创建图像大小调整器?

来自分类Dev

如何使用纯JAvaScript制作div大小调整器

来自分类Dev

无边框框架和默认控件。大小调整器不起作用

来自分类Dev

面板之间的元素在大小调整器中未对齐

来自分类Dev

无边框框架和默认控件。大小调整器不起作用

来自分类Dev

如何防止垂直大小调整器在wxformbuilder中将孩子完全向下扩展

来自分类Dev

Bash 批量图像调整器

来自分类Dev

相位调整器3调整大小后图像质量低

来自分类Dev

使用CSS将GIF大小调整为浏览器窗口尺寸

来自分类Dev

大小调整事件的侦听器

来自分类Dev

大小调整方向的侦听器

来自分类Dev

具有(双)三次插值的音频振荡器

来自分类Dev

Internet Explorer双三次背景图像缩放

来自分类Dev

使用imagemagick调整图像大小

来自分类Dev

具有天蓝色 blob 存储的图像调整器。通过调整器时返回“403 forbidden”

来自分类Dev

将JPG图像转换为PDF而不用使用ghostscript或itext调整图像大小

来自分类Dev

使用David J Bradshaw的iframe调整器

来自分类Dev

使用David J Bradshaw的iframe调整器

来自分类Dev

使用dd将映像后的分区大小调整到另一个驱动器

来自分类Dev

检测何时将浏览器窗口从特定大小调整为更大大小?

来自分类Dev

将html元素大小调整为最大浏览器大小

来自分类Dev

使用PHP imageftbbox-将图像大小调整为字体大小输出?

来自分类Dev

将CSS三次方贝塞尔曲线宽松转换为Javascript

来自分类Dev

将点列表转换为SVG三次分段Bezier曲线

来自分类Dev

引导图像大小调整

来自分类Dev

使用ARM NEON将8位图像大小调整为4

来自分类Dev

将 div 大小调整为包含图像的宽度

来自分类Dev

将 url 图像大小调整为相等的部分

Related 相关文章

  1. 1

    使用wxPython在框内嵌套大小调整器

  2. 2

    如何在PHP中创建图像大小调整器?

  3. 3

    如何使用纯JAvaScript制作div大小调整器

  4. 4

    无边框框架和默认控件。大小调整器不起作用

  5. 5

    面板之间的元素在大小调整器中未对齐

  6. 6

    无边框框架和默认控件。大小调整器不起作用

  7. 7

    如何防止垂直大小调整器在wxformbuilder中将孩子完全向下扩展

  8. 8

    Bash 批量图像调整器

  9. 9

    相位调整器3调整大小后图像质量低

  10. 10

    使用CSS将GIF大小调整为浏览器窗口尺寸

  11. 11

    大小调整事件的侦听器

  12. 12

    大小调整方向的侦听器

  13. 13

    具有(双)三次插值的音频振荡器

  14. 14

    Internet Explorer双三次背景图像缩放

  15. 15

    使用imagemagick调整图像大小

  16. 16

    具有天蓝色 blob 存储的图像调整器。通过调整器时返回“403 forbidden”

  17. 17

    将JPG图像转换为PDF而不用使用ghostscript或itext调整图像大小

  18. 18

    使用David J Bradshaw的iframe调整器

  19. 19

    使用David J Bradshaw的iframe调整器

  20. 20

    使用dd将映像后的分区大小调整到另一个驱动器

  21. 21

    检测何时将浏览器窗口从特定大小调整为更大大小?

  22. 22

    将html元素大小调整为最大浏览器大小

  23. 23

    使用PHP imageftbbox-将图像大小调整为字体大小输出?

  24. 24

    将CSS三次方贝塞尔曲线宽松转换为Javascript

  25. 25

    将点列表转换为SVG三次分段Bezier曲线

  26. 26

    引导图像大小调整

  27. 27

    使用ARM NEON将8位图像大小调整为4

  28. 28

    将 div 大小调整为包含图像的宽度

  29. 29

    将 url 图像大小调整为相等的部分

热门标签

归档