0

源 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(). 但是,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 上,不透明像素实际上返回 0.99999999976717(32 位浮点数)的 alpha 值。

4

1 回答 1

1

一种解决方案是:

  1. 创建一个具有与您要测试的图像相同大小的彩色背景的新法师。

  2. compositeImage使用和在新画布的顶部绘制图像COMPOSITE_ATOP

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

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

在代码中,这看起来像:

$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) { ["mean"]=> float(0) ["minima"]=> float(1.0E+37) ["maxima"]=> float(-1.0E-37) ["standardDeviation "]=> float(0) ["depth"]=> int(1) } 1 :array(5) { ["mean"]=> float(5764.6123956044) ["minima"]=> float(0) [ "最大值"]=> 浮点数(53619) ["标准偏差"]=> 浮点数(11888.331707876) ["深度"]=> int(15) } 2 :array(5) { ["mean"]=> 浮点数(2058.7978021978 ) ["minima"]=> float(0) ["maxima"]=> float(34951) ["standardDeviation"]=> float(5059.2862080476) ["depth"]=> int(15) } 4 :array( 5) { ["mean"]=> float(6324.2305054945) ["minima"]=> float(0) ["maxima"]=> float(46773) ["standardDeviation"]=> float(11356.366371237) ["depth"]=> int(15) } 8 :array(5) { ["mean"]=> float(46867.721934066) ["minima"]=> float(0) ["最大值"]=> 浮点数(65535) ["标准偏差"]=> 浮点数(26491.889090216) ["深度"]=> int(15) } 32 :array(5) { ["mean"]=> 浮点数(0) ["minima"]=> float(1.0E+37) ["maxima"]=> float(-1.0E-37) ["standardDeviation"]=> float(0) ["depth"]=> int(1 ) }float(0) ["minima"]=> float(1.0E+37) ["maxima"]=> float(-1.0E-37) ["standardDeviation"]=> float(0) ["depth"]= > int(1) }float(0) ["minima"]=> float(1.0E+37) ["maxima"]=> float(-1.0E-37) ["standardDeviation"]=> float(0) ["depth"]= > int(1) }

0 :array(5) { ["mean"]=> float(0) ["minima"]=> float(1.0E+37) ["maxima"]=> float(-1.0E-37) ["standardDeviation "]=> float(0) ["depth"]=> int(1) } 1 :array(5) { ["mean"]=> float(51766.576175824) ["minima"]=> float(0) [ "最大值"]=> 浮点数(65535) ["标准偏差"]=> 浮点数(19889.498582657) ["深度"]=> int(16) } 2 :array(5) { ["mean"]=> 浮点数(48461.548131868 ) ["minima"]=> float(0) ["maxima"]=> float(65535) ["standardDeviation"]=> float(24228.543381351) ["depth"]=> int(16) } 4 :array( 5) { ["mean"]=> float(5353.375032967) ["minima"]=> float(0) ["maxima"]=> float(43081) ["standardDeviation"]=> float(10139.362164338) ["depth"]=> int(16) } 8 :array(5) { ["mean"]=> float(0) ["minima"]=> float(0) ["最大值"]=> float(0) ["standardDeviation"]=> float(0) ["depth"]=> int(1) } 32 :array(5) { ["mean"]=> float(0) ["minima"]=> float(1.0E+37) ["maxima"]=> float(-1.0E-37) ["standardDeviation"]=> float(0) ["depth"]=> int(1 ) }]=> float(-1.0E-37) ["standardDeviation"]=> float(0) ["depth"]=> int(1) }]=> float(-1.0E-37) ["standardDeviation"]=> float(0) ["depth"]=> int(1) }

如果不是很明显,那两个数组肯定是不一样的。

1 :array(5) { ["mean"]=> float(5764.6123956044) 1 :array(5) { ["mean"]=> float(51766.576175824)

从理论上讲,您可以检查实际值getImageChannelStatistics- 如果您可以弄清楚这些值的实际含义,但比较方法可能更安全。

于 2013-11-13T15:36:08.453 回答