• 首页
  • vue
  • TypeScript
  • JavaScript
  • scss
  • css3
  • html5
  • php
  • MySQL
  • redis
  • jQuery
  • Imagick::resizeImage()

    (PECL imagick 2.0.0)

    Scales an image

    说明

    Imagick::resizeImage(int $columns,int $rows,int $filter,float $blur[,bool $bestfit= FALSE[,bool $legacy= FALSE]]): bool

    Scales an image to the desired dimensions with a filter.

    Note:参数$bestfit的特性在 Imagick 3.0.0 中已改变。在此版本以前,当目标尺寸设为 400x400 时,原尺寸为 200x150 的图像将不会被改变。自 Imagick 3.0.0 起,源图像将会被放大到 400x300 因为这将更好的适合目标尺寸。当使用参数$bestfit时,必须同时给出宽度和高度。

    参数

    $columns

    Width of the image

    $rows

    Height of the image

    $filter

    Refer to the list of filter constants.

    $blur

    The blur factor where > 1 is blurry,< 1 is sharp.

    $bestfit

    Optional fit parameter.

    返回值

    成功时返回TRUE

    更新日志

    版本说明
    2.1.0 Added optional fit parameter. This method now supports proportional scaling. Pass zero as either parameter for proportional scaling.

    范例

    Example #1 Imagick::resizeImage()

    <?php
    function resizeImage($imagePath, $width, $height, $filterType, $blur, $bestFit, $cropZoom) {
        //The blur factor where &gt; 1 is blurry, &lt; 1 is sharp.
        $imagick = new \Imagick(realpath($imagePath));
        $imagick->resizeImage($width, $height, $filterType, $blur, $bestFit);
        $cropWidth = $imagick->getImageWidth();
        $cropHeight = $imagick->getImageHeight();
        if ($cropZoom) {
            $newWidth = $cropWidth / 2;
            $newHeight = $cropHeight / 2;
            $imagick->cropimage(
                $newWidth,
                $newHeight,
                ($cropWidth - $newWidth) / 2,
                ($cropHeight - $newHeight) / 2
            );
            $imagick->scaleimage(
                $imagick->getImageWidth() * 4,
                $imagick->getImageHeight() * 4
            );
        }
        header("Content-Type: image/jpg");
        echo $imagick->getImageBlob();
    }
    ?>
    
    Having to do alot of resizing, i needed to know the speeds of the different resize filters.
    This was how long it took to resize a 5906x5906 JPEG image to 1181x1181.
    FILTER_POINT took: 0.334532976151 seconds
    FILTER_BOX took: 0.777871131897 seconds
    FILTER_TRIANGLE took: 1.3695909977 seconds
    FILTER_HERMITE took: 1.35866093636 seconds
    FILTER_HANNING took: 4.88722896576 seconds
    FILTER_HAMMING took: 4.88665103912 seconds
    FILTER_BLACKMAN took: 4.89026689529 seconds
    FILTER_GAUSSIAN took: 1.93553304672 seconds
    FILTER_QUADRATIC took: 1.93322920799 seconds
    FILTER_CUBIC took: 2.58396601677 seconds
    FILTER_CATROM took: 2.58508896828 seconds
    FILTER_MITCHELL took: 2.58368492126 seconds
    FILTER_LANCZOS took: 3.74232912064 seconds
    FILTER_BESSEL took: 4.03305602074 seconds
    FILTER_SINC took: 4.90098690987 seconds 
    I ended up choosing CATROM as it has a very similar result to LANCZOS, but is significantly faster.
    Some size, image and filter and blur combinations causes artifacts or even make image completely scrambled. As far, as I see, it happens with blur values smaller than 0.25 (sometimes less) and goes worse to the point of 0 - black image. Sometimes only some values gives artifacts, like Hanning with my test image: 0.0 blur is fine, 0.1 produces artefacts.
    Affected filters are e.g. Catrom, sinc, cubic, quadratic, while unaffected are e.g. Lanczos and Hanning. The problem seems to be the domain of the filter algorithms, not IMagick implementation. This image shows three filters: http://i.imgur.com/HcdwoUS.jpg
    Sometimes test image could look fine, but other not, so if you are using affected filters, the 0.5 value should be safe.
    This test script takes example image (you can download and use http://i.imgur.com/KsTJpFr.jpg which is affected) and creates resized images in the same directory for every filter and one of four blur values, with naming like "test.jpg.sinc.0.1.jpg" for "test.jpg" input.
    <?php
      $imgPath = 'imgtest/test.jpg'; // set your image file
      $testBlurs = [0, 0.1, 0.2, 0.5]; // test these blur values
      $im = new IMagick();
      $im->readImage($imgPath);
      
      foreach ((new ReflectionClass('IMagick'))->getConstants() as $n => $f) {
        if (strncmp($n, 'FILTER_', 7) === 0) { // get available IMagick filters
          $filterName = strtolower(substr($n, 7)); // extract filter name from constant
          foreach ($testBlurs as $blur) {
            $imSize = clone $im;
            $imSize->resizeImage(500, 500, $f, $blur, true);
            $imSize->writeImage(sprintf("%s-%s-%.1f.jpg", $imgPath, $filterName, $blur));
            $imSize->destroy();
          }
        }
      }
      
    ?>
    
    blur: > 1 is blurry, < 1 is sharp
    To create a nice thumbnail (LANCZOS is the slowest filter):
    <?php
    $thumb = new Imagick();
    $thumb->readImage('myimage.gif');  $thumb->resizeImage(320,240,Imagick::FILTER_LANCZOS,1);
    $thumb->writeImage('mythumb.gif');
    $thumb->clear();
    $thumb->destroy(); 
    ?>
    Or, a shorter version of the same:
    <?php
    $thumb = new Imagick('myimage.gif');
    $thumb->resizeImage(320,240,Imagick::FILTER_LANCZOS,1);
    $thumb->writeImage('mythumb.gif');
    $thumb->destroy(); 
    ?>
    
    The changelog comment
     "2.1.0 Added optional fit parameter. This method now supports proportional scaling. Pass zero as either parameter for proportional scaling."
    is poorly structured and therefore IMO misleading. Yes for proportional scaling you pass 0 as either parameter... however this is *not* true if you use the optional fit param. When bestfit == true you must specify a *non-zero* value for both columns and rows. Note it WILL still scale proportionally e.g.
      Imagick::resizeImage ( 200, 200, imagick::FILTER_LANCZOS, 1, TRUE)
    will resize a 1000x750 image to 200x150
    So for proportional resizing:
    without "bestfit"
      Imagick::resizeImage ( 200, 0, imagick::FILTER_LANCZOS, 1)
    with "bestfit"
      Imagick::resizeImage ( 200, 200, imagick::FILTER_LANCZOS, 1, TRUE)
    In our linux environment, using resizeImage with any filter produced extremely high CPU Utilization (in the range of 40-50%) while doing batch resizing.
    We switched to scaleImage, which produces similar results to FILTER_BOX, and CPU Utilization dropped to 2-3%. 
    Using XHProf to profile the two batch jobs showed amazing decreases in CPU Time, so if you're doing a lot of picture resizing, it might be beneficial to use scaleImage instead of resizeImage, as it seems to be much much more efficient.
    To avoid upscaling when using the "bestfit" param, check the image dimensions before resizing:
    <?php
      $image = new Imagick( $filename );
      $imageprops = $image->getImageGeometry();
      if ($imageprops['width'] <= 200 && $imageprops['height'] <= 200) {
        // don't upscale
      } else {
        $image->resizeImage(200,200, imagick::FILTER_LANCZOS, 0.9, true);
      }
    ?>
    
    Use setImageOpacity(1.0) before resizing, for proper handling of transparency in png and gif.