使用 PHP 创建浮雕效果:在底部边缘添加白色边框,在其他边缘添加黑色边框,图像的其余部分应为 5% 黑色

Use PHP to create embossing effect: add white border to bottom edges and black border to other edges, rest of image should be 5% black

我想知道是否可以使用 PHP 在用户上传的徽标上创建浮雕效果。

效果(根据 Photoshop 部门的说法)可以通过将徽标的内容转换为全黑(因此它将是一种颜色)并使 'layer' 5% 填充(所以基本上它变成 95% 透明)。之后,他们会在徽标的 top/left/right 边缘添加黑色边框,并在徽标的底部边缘添加白色边框。并且只是边缘,而不是图像本身的外部;标识内容的边缘需要描边

由于我在图像处理方面的知名度不高,我想知道是否有一些 PHP 专家可以帮助我 out/point 我在正确的方向上如何做这件事?

所以总结起来,我需要的是4样东西:

如果可以在 CSS 中为 IE10 及更高版本的浏览器实现,这也是一个很好的解决方案。提前致谢!

编辑

这是艺术家在 image/background/pattern 之上创建的徽标示例:http://picpaste.com/embos-example-ngxfSAj5.png - 他们以与他们最初告诉我他们会做的方式有点不同: ) 在 Photoshop 中,他们添加了一个从上到下的黑色内阴影,以及一个从下到上的白色阴影

看来我问的问题不对.. 将效果从荷兰语 (Preeg) 翻译成英语时,我以为我需要浮雕效果.. 但我发现 PHP function shadeImage 是我想要的。为了帮助其他人,我会 post 我做了什么来实现这一目标。

要使用 shadeImage,您必须提供 black/white 图片。那是我第一次尝试该功能时出错的地方。所以我首先做了一个函数,根据每个像素的 alpha 通道将图像转换为 black/grey/white。之后我使用了 shadeImage。生成的图像确实有背景,必须将其删除。我尝试使用 paintTransparentImage 之类的东西,但在我的所有测试中都没有用,所以我制作了一个自定义函数,通过再次循环每个像素。最后我将所有像素设置为 0.35 的 alpha 通道值,使图像有点 'softer' 并且可以在背景上使用。这是完整的函数:

    public function createEmbossedLogo($imagePath, $embossedFilePath) {
        // initialize Imagick and load the image
        $imagick = new \Imagick(realpath($imagePath));

        // make sure we are using PNG, so we can use the alpha channel
        $imagick->setImageFormat('png');

        // resize the logo, so we do not have to process too many pixels
        $imagick->resizeImage(200, null,\Imagick::FILTER_CATROM,1);

        // if the image does not have any margin around the content,
        // the shade would be cut off at the sides,
        // so we add an invisible border of 5 pixels, to add some margin
        $imagick->borderImage('rgba(255,0,0,0)',5, 5);

        // now we have to convert the image to a black/white image, using only the alpha channel
        // and use the alpha channel value as the R/G/B channel values

        // load the pixels of the image
        $imageIterator = $imagick->getPixelIterator();
        foreach ($imageIterator as $row => $pixels) { /* Loop through pixel rows */
            foreach ($pixels as $column => $pixel) { /* Loop through the pixels in the row (columns) */
                /** @var $pixel \ImagickPixel */
                $nor_color = $pixel->getColor(true); //normalized color

                // the alpha channel will be 0 if it is completely invisible and 1 if visibile
                // but can be any value in between 0-1
                // by using the alpha channel as the white/grey/black value, we create an alpha map
                $alpha = $nor_color['a'];
                $rgbValue = $alpha*255;
                $pixel->setColor('rgba('.$rgbValue.','.$rgbValue.','.$rgbValue.',1');
            }

            $imageIterator->syncIterator(); /* Sync the iterator, this is important to do on each iteration */
        }

        // add the shading, the first parameter makes sure that all the 'to be removed' pixels
        // are the same color, so we can find them in the next loop through all pixels
        // they would otherwise be black, one of the colors we do need to keep in the result
        $imagick->shadeImage(true,270,45);

        // the shadeImage function will make all the pixels grey that should be transparent
        // so we loop over all the pixels in the image once again to remove them
        $imageIterator = $imagick->getPixelIterator();
        $colorFound = false;
        $colorRange = 10;
        foreach ($imageIterator as $row => $pixels) { /* Loop through pixel rows */
            foreach ($pixels as $column => $pixel) { /* Loop through the pixels in the row (columns) */
                /** @var $pixel \ImagickPixel */
                $color = $pixel->getColor(); //normalized color
                if (!$colorFound) {
                    // since added some margin around the image, we can take the first pixel
                    // of the top left corner, and use it as the color to make transparent
                    // and since the image is in black/white, we only need one 'color' channel
                    $colorFound = array();
                    $colorFound['r'] = $color['r'];
                }

                // the default alpha for pixels to keep is 1
                $alpha = 1;

                // see if the color of this pixel is close to that of the 'color to be deleted'
                // if so, we will not totally delete it, but change the alpha channel accordingly
                $diff = abs($color['r']-$colorFound['r']);
                if ($diff<=$colorRange) {
                    // set alpha value for this pixel, based on the difference from the removed color
                    $alpha = $diff / $colorRange;
                }

                // the entire opacity of the image has to brought down, to make the image a bit 'softer'
                $alpha *= 0.35;

                // this pixel matches the 'to be removed' color, so we set it to a new value with alpha 0
                $pixel->setColor('rgba('.$color['r'].','.$color['g'].','.$color['b'].','.$alpha.')');
            }

            $imageIterator->syncIterator(); /* Sync the iterator, this is important to do on each iteration */
        }

        // remove any excess margins that are not needed
        $imagick->trimImage(0);

        // store the image
        $imagick->writeImage($embossedFilePath);
    }