使用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部门的说法)可以通过将logo的内容转换为全黑来实现(所以它将是一种颜色),并使该"图层"填充5%(所以基本上它变成了95%的透明度)。之后,他们会在logo的上/左/右边缘添加黑色边框,在logo的下边缘添加白色边框。只是边缘,而不是图像本身的外部;标志内容的边缘需要描摹。

由于我在图像处理方面并不出名,我想知道是否有一些PHP专家可以帮助我/指出我在正确的方向上如何做到这一点?

所以总结起来,我需要的是4件事:

  • 将图像内容转换为全黑(但保持透明)
  • 设置图像95%透明
  • 在图片的上/左/右边缘添加黑色边框
  • 在图片
  • 内容的底部边缘添加一个白色边框

如果这可以在IE10及以上浏览器的CSS中实现,这将是一个很好的解决方案。提前感谢!

编辑

这是一个由艺术家创建的徽标的例子,在图像/背景/图案的顶部:http://picpaste.com/embos-example-ngxfSAj5.png -他们做的方式有点不同,因为他们第一次告诉我他们会这样做:)在Photoshop中,他们从上到下添加了黑色的内阴影,从下到上添加了白色的投影

看来我没有问对问题。当把荷兰语(Preeg)的效果翻译成英语时,我想我需要一个浮雕效果。但我发现PHP函数shadeImage是我想要的。为了帮助别人,我将把我做到这一点的方法贴出来。

要使用shadeImage,你必须提供一个黑白图像。这就是我第一次尝试这个函数时出错的地方。因此,我首先创建了一个函数,根据每个像素的alpha通道将图像转换为黑/灰/白。之后我使用了shadeImage。生成的图像确实有背景,必须删除。我尝试使用paintTransparentImage之类的东西,但这在我所有的测试中都不起作用,所以我创建了一个自定义函数,通过再次循环每个像素。最后,我将所有像素的alpha通道值设置为0.35,以使图像在背景上更"柔和"和可用。下面是完整的函数:

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