使用生成的Imagick图像遮罩图像

时间:2016-12-26 19:30:53

标签: php image imagick bezier

我需要知道如何使用Imagick屏蔽任何方形图像。这是我到目前为止的代码,但图像没有被正确掩盖:

获取图片

$srcFile = 'filename.png';
$image = new Imagick($srcFile);

将图像裁剪为方

$d = $image->getImageGeometry();
$src_width = $d['width']; 
$src_height = $d['height'];
$thumbSize = min(max($src_width, $src_height), abs($thumbSize));        
if ($src_width < $src_height) {
    $image->cropImage($src_width, $src_width, 0, (($src_height - $src_width)/2));
} else {
    $image->cropImage($src_height, $src_height, (($src_width - $src_height)/2), 0);
}

调整图片大小

$image->thumbnailImage($thumbSize, $thumbSize, 1);

使用贝塞尔曲线形状裁剪/遮罩图像

$image->compositeImage(bezier($thumbSize, $thumbSize), Imagick::COMPOSITE_COPYOPACITY, 0, 0);

bezier函数创建一个如下所示的形状:

bezier mask shape

function bezier($width, $height) {
    $fillColor = "#000";
    $draw = new ImagickDraw();

用黑色填充未遮罩的部分

    $fillColor = new ImagickPixel($fillColor);
    $draw->setFillColor($fillColor);
    $smoothPointsSet = [
        [
            ['x' => 0.0 * $width, 'y' => 0.5 * $width],
            ['x' => 0.0 * $width, 'y' => 0.905 * $width],
            ['x' => 0.095 * $width, 'y' => 1.0 * $width],
            ['x' => 0.5 * $width, 'y' => 1.0 * $width]
        ], [
            ['x' => 0.5 * $width, 'y' => 1.0 * $width],
            ['x' => 0.905 * $width, 'y' => 1.0 * $width],
            ['x' => 1.0 * $width, 'y' => 0.905 * $width],
            ['x' => 1.0 * $width, 'y' => 0.5 * $width]
        ], [
            ['x' => 1.0 * $width, 'y' => 0.5 * $width],
            ['x' => 1.0 * $width, 'y' => 0.095 * $width],
            ['x' => 0.905 * $width, 'y' => 0.0 * $width],
            ['x' => 0.5 * $width, 'y' => 0.0 * $width]
        ], [
            ['x' => 0.5 * $width, 'y' => 0.0 * $width],
            ['x' => 0.095 * $width, 'y' => 0.0 * $width],
            ['x' => 0.0 * $width, 'y' => 0.095 * $width],
            ['x' => 0.0 * $width, 'y' => 0.5 * $width]
        ]
    ];

    foreach ($smoothPointsSet as $points) {
        $draw->bezier($points);
    }

bezier积分不填充中间的正方形,因此请手动填充

    $points = [
        ['x' => $width * 0.5, 'y' => 0.0],
        ['x' => 0.0, 'y' => $height * 0.5],
        ['x' => $width * 0.5, 'y' => $height],
        ['x' => $width, 'y' => $height * 0.5]
    ];
    $draw->polygon($points);

将抽屉图像复制到新的透明Imagick图像

    $imagick = new Imagick();
    $imagick->newImage($width, $width, "none");

从这里开始,我尝试了各种属性。我没有得到任何令人满意的结果 - 图像几乎总是没有被掩盖。

    #$imagick->setImageAlphaChannel(Imagick::ALPHACHANNEL_SHAPE);
    #$imagick->setImageFormat("png");

    $imagick->drawImage($draw);

    #$imagick->setImageMatte(false);

    return $imagick;
}

如果我能知道问题所在以及如何解决问题,我将非常高兴。我在SO上发现了各种不适合我的答案:

使用$dude->setImageMatte(1); Using a transparent PNG as a clip mask

使用$base->compositeImage($mask, Imagick::COMPOSITE_DSTIN, 0, 0, Imagick::CHANNEL_ALPHA); How to use Imagick to merge and mask images?

不幸的是我无法解决问题。

1 个答案:

答案 0 :(得分:0)

问题是图像存储为JPEG,因此透明部分变黑。这是我使用的代码:

$mask = bezier($thumbSize, $thumbSize);

// Copy opacity mask
if ($image->getImageMatte()) {
    $image->compositeImage($mask, Imagick::COMPOSITE_DSTIN, 0, 0, Imagick::CHANNEL_ALPHA);
} else {
    $image->compositeImage($mask, Imagick::COMPOSITE_COPYOPACITY, 0, 0);
}

$image->setImageBackgroundColor(new ImagickPixel('white'));
#$image->setImageAlphaChannel(Imagick::ALPHACHANNEL_DEACTIVATE);
$image = $image->flattenImages();

在函数贝塞尔:

$imagick = new Imagick();
$imagick->newImage($width, $width, "none");
$imagick->setImageBackgroundColor(new ImagickPixel('transparent'));
#$imagick->setImageAlphaChannel(Imagick::ALPHACHANNEL_SHAPE);
$imagick->setImageFormat("png");

//Render the draw commands in the ImagickDraw object 
//into the image.
$imagick->drawImage($draw);
$imagick->negateImage(FALSE);


return $imagick;