如何检测裁剪的PNG是否具有透明度

时间:2013-11-12 15:34:21

标签: php image-processing imagick

源PNG图像将由PHP使用Imagick根据用户输入进行裁剪。结果是裁剪后的图像可能有也可能没有透明像素。我正在寻找一种方法来检测裁剪的图像是否具有透明度是或否,因此我可以将不透明的PNG转换为JPG。

这是我加载图片的代码:

// Get user input
$src = $_POST['src'];
$resize = json_decode($_POST['selection_data']);

// Load image (source image has transparency)
$dst = new Imagick($src);

// Crop image (the part that will be cropped is fully opaque)
$dst->cropImage($resize->selW, $resize->selH, $resize->selX, $resize->selY);
$dst->resizeImage($resize->dstW, $resize->dstH, imagick::FILTER_CATROM, 0.9, false);

在此之后,我可以使用$dst->getImageAlphaChannel()检查Alpha通道。但是,无论裁剪的图像是否包含任何透明像素,都会返回true,因为它是在加载源图像时设置的(具有透明度)。

检查透明像素的另一种方法是查看每个像素的alpha值小于1 *:

$alpha = false;
for ($x = 0; $x < $resize->dstW; $x++)
{
    for ($y = 0; $y < $resize->dstH; $y++)
    {               
        if ($dst->getImagePixelColor($x, $y)->getColorValue(Imagick::COLOR_ALPHA) < 1)
        {
            $alpha = true;
            break 2;
        }
    }
}

但对于大图像(1000x1000),执行此操作需要30秒以上,这并不理想。

检测图像是否有透明像素的最快方法是什么?

*:在我正在测试的Debian Wheezy上,不透明像素实际上返回的alpha值为0.99999999976717(32位浮点数)。

1 个答案:

答案 0 :(得分:1)

一种解决方案是:

  1. 创建一个新的图像,其背景颜色与您要测试的图像大小相同。

  2. 使用compositeImageCOMPOSITE_ATOP在新画布的顶部绘制图像。

  3. 获取所有颜色通道的图像统计信息。

  4. 对于任何完全没有任何透明度的图像,这两个图像应该具有完全相同的每个颜色通道的图像统计数据。

    在代码中,这看起来像:

    $imagick = new Imagick(realpath("../images/fnord.png"));
    
    $newCanvas = new Imagick();
    $newCanvas->newImage($imagick->getImageWidth(), $imagick->getImageHeight(), 'rgba(255, 255, 0, 1)', 'png');
    $newCanvas->compositeimage($imagick, Imagick::COMPOSITE_ATOP, 0, 0);
    
    function dumpInfo(Imagick $imagick) {
    
        $identifyInfo = $imagick->getImageChannelStatistics();
    
        foreach ($identifyInfo as $key => $value) {
    
            echo "$key :";
    
            if (is_array($value) == true) {
                var_dump($value);
            }
            else {
                echo $value;
            }
    
            echo "<br/>";
        }
    }
    
    dumpInfo($imagick);
    echo "<br/><br/>";
    dumpInfo($newCanvas);
    

    透明图像给出输出:

      

    0:array(5){[&#34; mean&#34;] =&gt; float(0)[&#34; minima&#34;] =&gt;浮子(1.0E + 37)   [&#34;最大值&#34;] =&GT; float(-1.0E-37)[&#34; standardDeviation&#34;] =&gt;浮动(0)   [&#34;深度&#34;] =&GT; int(1)} 1:array(5){[&#34; mean&#34;] =&gt;浮动(5764.6123956044)   [&#34;最小值&#34;] =&GT; float(0)[&#34; maxima&#34;] =&gt;浮动(53619)   [&#34; standardDeviation&#34;] =&GT; float(11888.331707876)[&#34; depth&#34;] =&gt; int(15)}   2:array(5){[&#34; mean&#34;] =&gt; float(2058.7978021978)[&#34; minima&#34;] =&gt;浮动(0)   [&#34;最大值&#34;] =&GT; float(34951)[&#34; standardDeviation&#34;] =&gt;   float(5059.2862080476)[&#34; depth&#34;] =&gt; int(15)} 4:array(5){[&#34; mean&#34;] =&gt;   float(6324.2305054945)[&#34; minima&#34;] =&gt; float(0)[&#34; maxima&#34;] =&gt;浮动(46773)   [&#34; standardDeviation&#34;] =&GT; float(11356.366371237)[&#34; depth&#34;] =&gt; int(15)}   8:array(5){[&#34; mean&#34;] =&gt; float(46867.721934066)[&#34; minima&#34;] =&gt;浮动(0)   [&#34;最大值&#34;] =&GT; float(65535)[&#34; standardDeviation&#34;] =&gt;   float(26491.889090216)[&#34; depth&#34;] =&gt; int(15)} 32:array(5){   [&#34;平均&#34;] =&GT; float(0)[&#34; minima&#34;] =&gt; float(1.0E + 37)[&#34; maxima&#34;] =&gt;   float(-1.0E-37)[&#34; standardDeviation&#34;] =&gt; float(0)[&#34; depth&#34;] =&gt; int(1)}

         

    0:array(5){[&#34; mean&#34;] =&gt; float(0)[&#34; minima&#34;] =&gt;浮子(1.0E + 37)   [&#34;最大值&#34;] =&GT; float(-1.0E-37)[&#34; standardDeviation&#34;] =&gt;浮动(0)   [&#34;深度&#34;] =&GT; int(1)} 1:array(5){[&#34; mean&#34;] =&gt;浮动(51766.576175824)   [&#34;最小值&#34;] =&GT; float(0)[&#34; maxima&#34;] =&gt;浮动(65535)   [&#34; standardDeviation&#34;] =&GT; float(19889.498582657)[&#34; depth&#34;] =&gt; int(16)}   2:array(5){[&#34; mean&#34;] =&gt; float(48461.548131868)[&#34; minima&#34;] =&gt;浮动(0)   [&#34;最大值&#34;] =&GT; float(65535)[&#34; standardDeviation&#34;] =&gt;   float(24228.543381351)[&#34; depth&#34;] =&gt; int(16)} 4:array(5){[&#34; mean&#34;] =&gt;   float(5353.375032967)[&#34; minima&#34;] =&gt; float(0)[&#34; maxima&#34;] =&gt;浮动(43081)   [&#34; standardDeviation&#34;] =&GT; float(10139.362164338)[&#34; depth&#34;] =&gt; int(16)}   8:array(5){[&#34; mean&#34;] =&gt; float(0)[&#34; minima&#34;] =&gt; float(0)[&#34; maxima&#34;] =&gt;   float(0)[&#34; standardDeviation&#34;] =&gt; float(0)[&#34; depth&#34;] =&gt; int(1)} 32   :array(5){[&#34; mean&#34;] =&gt; float(0)[&#34; minima&#34;] =&gt;浮子(1.0E + 37)   [&#34;最大值&#34;] =&GT; float(-1.0E-37)[&#34; standardDeviation&#34;] =&gt;浮动(0)   [&#34;深度&#34;] =&GT; int(1)}

    如果不明显,那两个阵列绝对不一样。

      

    1:array(5){[&#34; mean&#34;] =&gt;浮动(5764.6123956044)   1:array(5){[&#34; mean&#34;] =&gt;浮动(51766.576175824)

    理论上你可以只检查getImageChannelStatistics的实际值 - 如果你能弄清楚这些值实际意味着什么,但比较方法可能更安全。