【问题标题】:Mask images with a generated Imagick image使用生成的 Imagick 图像遮罩图像
【发布时间】:2016-12-26 19:30:53
【问题描述】:

我需要知道如何使用 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 函数创建的形状如下所示:

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

贝塞尔点不填充中间的正方形,所以手动填充它

    $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-&gt;setImageMatte(1); Using a transparent PNG as a clip mask

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

很遗憾,我无法解决问题。

【问题讨论】:

    标签: php image imagick bezier


    【解决方案1】:

    问题在于图像以 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;
    

    【讨论】:

    • 将帖子发布到 imagemagick 邮件列表,或者访问他们的 IRC 频道,或者无论他们的直接联系方式是什么,让他们知道 image magick 显然不会在用户以不支持所用功能的格式保存图像。将位图中带有 Alpha 通道的图像保存为 JPEG 至少应该会给您一个控制台警告,这将使您能够立即发现并解决问题。
    • “让他们知道图像魔法显然不会在用户以某种格式保存图像时警告用户”这可能是设计使然。 ImageMagick 公开的 C api 背后的理念是做用户告诉它做的事情,假设他们知道自己在做什么。将具有透明度的图像保存为 Jpeg 是正常的事情(有时),所以它只是这样做,而不是怀疑用户的意图。
    猜你喜欢
    • 1970-01-01
    • 2018-05-29
    • 2016-01-07
    • 2022-10-23
    • 2013-01-11
    • 1970-01-01
    • 1970-01-01
    • 2016-06-09
    • 1970-01-01
    相关资源
    最近更新 更多