提问人:Bill in Kansas City 提问时间:7/17/2023 更新时间:7/17/2023 访问量:34
PHP:图像叠加,仅在底部图像不透明的情况下将顶部图像应用于底部图像
PHP: image overlay, applying top image to bottom image only where bottom image isn't transparent
问:
你用谷歌搜索过吗?是的,十几篇或更多文章。
你搜索过 SO 吗?是的,因为我正在输入我的问题,并且在此之前多次输入。
你搜索过PHP文档吗?是的。
我找到的信息都没有解决我要问的特定问题。
当您访问服装网站并为紧身裤等颜色选择时,只有服装的颜色会发生变化。这是相同的图像,只是对服装应用了滤镜。
我以前在PHP中见过这样做,所以我知道这是可能的。基础层,模型层,然后是具有透明背景的灰度服装。下一层是纯色或具有透明背景的图案,并与服装混合,以保留高光和阴影,然后将混合的服装图层叠加在模型上,模型叠加在背景上。
我尝试过 Imagick、GD 和几个库,但在每种情况下,彩色/图案覆盖层不仅限于服装:它显示为每一层上浮动的颜色/图案块。
COMPOSITE_ATOP让我部分到达那里,但阴影和高光没有显示出来。如何将叠加层限制为服装图层中的非透明像素?我错过了什么?(下图)
我包含了 Imagick 代码,因为它比 GD 更简洁,但此时我对任何事情都持开放态度。
<?php
// PHP8.1
$backgroundImage = new Imagick('./img/background.png');
$shadows = new Imagick('./img/feet.png');
$backgroundImage->compositeImage($shadows, Imagick::COMPOSITE_DEFAULT, 0, 0);
$rightleg = new Imagick('./img/right-leg.png');
$w = $rightleg->getImageWidth();
$h = $rightleg->getImageHeight();
$image = new Imagick('./img/right-leg-color.png');
$rightleg->compositeImage($image, Imagick::COMPOSITE_OVERLAY, 0, 0);
$backgroundImage->compositeImage($rightleg, Imagick::COMPOSITE_DEFAULT, 0, 0);
$leftleg = new Imagick('./img/left-leg.png');
$backgroundImage->compositeImage($leftleg, Imagick::COMPOSITE_DEFAULT, 0, 0);
if (true) {
header('Content-Type: image/png');
echo $backgroundImage;
} else {
$rightleg->writeImage('test.png');
}
// Clean up resources
$backgroundImage->clear();
$backgroundImage->destroy();
$shadows->clear();
$shadows->destroy();
$rightleg->clear();
$rightleg->destroy();
$leftleg->clear();
$leftleg->destroy();
答:
0赞
Bill in Kansas City
7/17/2023
#1
这个问题的解决方案是使用 COMPOSITE_ATOP 将颜色放在目标的副本上:这具有类似蒙版的效果,其中颜色仅限于非透明像素。创建蒙版形状后,您可以将灰色原件合成到彩色蒙版图层上以应用光影。
$rightleg = new Imagick('./img/right-leg.png');
$rightmask = new Imagick('./img/right-leg.png');
$colorful = new Imagick('./img/right-leg-color.png');
// composite the colors over original element copy
$rightmask->compositeImage($colorful, Imagick::COMPOSITE_ATOP, 0, 0);
// now apply highlights and shadows using the original element
$rightmask->compositeImage($rightleg, Imagick::COMPOSITE_BUMPMAP, 0, 0);
如果有更好的方式,我愿意听到它,但这对我有用。
评论