如何将 2 个图像与 PHP(GD-GD2 库)混合,如乘法、颜色燃烧、颜色道奇等
Posted
技术标签:
【中文标题】如何将 2 个图像与 PHP(GD-GD2 库)混合,如乘法、颜色燃烧、颜色道奇等【英文标题】:How to blend 2 images with PHP (GD-GD2 Library) like multiply, colorburn, colordodge and others 【发布时间】:2013-03-16 15:12:56 【问题描述】:我想用 GD 库在 php 中混合两个图像——例如乘法、叠加和其他混合模式。
我的图片 = İimage1.jpg -- imageblend.jpg 或 image3.png
请帮我写例子还是一步一步教我?我找到了一些示例,但它们不起作用。
【问题讨论】:
感谢@ultranaut 的编辑。 【参考方案1】:在 GD 中内置的混合模式并不多,因此您必须自己实现它们。不幸的是,它会比原生 C 实现慢得多,但这是可能的。只需加载两个图像并遍历整个基础图像,应用混合模式将每个单独的像素从顶部图像复制到基础图像。加/减/乘真的很简单,正常的 alpha 混合相当简单(尽管只要你正确使用 imagealphablending
,alpha 混合就内置了)。我不知道颜色加深或颜色减淡的算法,但我相信快速搜索会找到如何做到这一点。至于overlay,原来在复制顶图之前使用imagelayereffect
其实是GD内置的。
我从permadi.com 中提取了这段代码以获得叠加效果。我还添加了一些用于乘法效果的替代代码,以向您展示如何将 PHP 用于混合模式算法。此代码假定顶部图像在任一维度上都不大于基本图像。
<?php
// GD images can be true-color or indexed color. This makes a difference for getting
// and setting pixels so we'll take note of each image.
// Load the base image. For overlays, this should be the template ("overlay.png" in source)
$baseImage = imagecreatefrompng("base.png");
$baseIsTrueColor = imageistruecolor($baseImage);
// Load the image to blend on top.
$topImage = imagecreatefrompng("top.png");
$topIsTrueColor = imageistruecolor($topImage);
// Get image dimensions
$baseWidth = imagesx($baseImage);
$baseHeight = imagesy($baseImage);
$topWidth = imagesx($topImage);
$topHeight = imagesy($topImage);
// Destination X and Y - these values will center $topImage within $baseImage:
$destX = ($baseWidth - $topWidth) / 2;
$destY = ($baseHeight - $topHeight) / 2;
// OVERLAY MODE
// This line causes all GD operations to use the overlay algorithm
// when blending pixels together.
imagelayereffect($baseImage, IMG_EFFECT_OVERLAY);
// Blend the top image onto the base image.
imagecopy(
$baseImage, // destination
$topImage, // source
// destination x and y
$destX, $destY,
// x, y, width, and height of the area of the source to copy
0, 0, $topWidth, $topHeight);
// OVERLAY
// MULTIPLY MODE
// Because we can't just use imagecopy, we have to iterate over all the pixels in
// the entire image in order to apply the multiply algorithm to each individual pixel.
// There is probably an easier way to handle true-color vs. indexed color in this
// section but without testing the code this was the most likely to work. Depending on
// how `imagecolorsforindex` and `imagecolorclosestalpha` work this section might work
// a lot simpler.
for ($x = 0; $x < $topWidth; ++$x)
for ($y = 0; $y < $topHeight; ++$y)
// First get the colors for the base and top pixels.
$color = imagecolorat($baseImage, $x + $destX, $y + $destY);
// If the image is true-color, we simply use bitwise operations to separate out
// red, green, blue, and alpha from the result of imagecolorat above.
if ($baseIsTrueColor)
$baseColor = array(
'red' => ($color >> 16) & 0xFF,
'green' => ($color >> 8) & 0xFF,
'blue' => $color & 0xFF,
'alpha' => ($color & 0x7F000000) >> 24,
);
// If the image uses indexed color, we can get the color components by looking up
// the color index in the image's color table.
else
$baseColor = imagecolorsforindex($baseImage, $color);
$color = imagecolorat($topImage, $x, $y);
// If the image is true-color, we simply use bitwise operations to separate out
// red, green, blue, and alpha from the result of imagecolorat above.
if ($topIsTrueColor)
$topColor = array(
'red' => ($color >> 16) & 0xFF,
'green' => ($color >> 8) & 0xFF,
'blue' => $color & 0xFF,
'alpha' => ($color & 0x7F000000) >> 24,
);
// If the image uses indexed color, we can get the color components by looking up
// the color index in the image's color table.
else
$topColor = imagecolorsforindex($topImage, $color);
// Now perform the multiply algorithm.
$destColor = array(
'red' => intval($baseColor['red'] * ($topColor['red'] / 255.0)),
'green' => intval($baseColor['green'] * ($topColor['green'] / 255.0)),
'blue' => intval($baseColor['blue'] * ($topColor['blue'] / 255.0)),
'alpha' => intval($baseColor['alpha'] * ($topColor['alpha'] / 127.0)),
);
// Now set the destination pixel.
$colorIndex = imagecolorallocatealpha($baseImage, $destColor['red'], $destColor['green'], $destColor['blue'], $destColor['alpha']);
// If we failed to allocate the color, try to find the already allocated color
// that is closest to what we want.
if ($colorIndex === FALSE)
$colorIndex = imagecolorclosestalpha($baseImage, $destColor['red'], $destColor['green'], $destColor['blue'], $destColor['alpha']);
// Now that we have a valid color index, set the pixel to that color.
imagesetpixel($baseImage, $x + $destX, $y + $destY, $colorIndex);
// MULTIPLY
// Set type of image and send the output
header("Content-type: image/png");
imagepng($baseImage);
// Release memory
imagedestroy($baseImage);
imagedestroy($topImage);
?>
我没有测试过代码,所以它可能无法正常工作,而且几乎可以肯定它比它需要的更复杂,但它应该作为你自己做这些事情的一个很好的起点。
【讨论】:
谢谢 @meustrus.. 我发现了一些算法 İts Wroten on php clases。但我不明白。我想学它。循序渐进 我添加了一些代码来向您展示如何实现叠加和乘法混合模式。 非常感谢@meustrus.. 该代码对我很有帮助..您的描述对学习此代码很有帮助.. 小心 meustrus..跨度> 乘法完美。谢谢你!有人知道它如何适用于其他混合模式吗? 刚刚做了一个快速的谷歌搜索,发现了这个:deepskycolors.com/archive/2010/04/21/…。所以对于颜色燃烧(1 - (1-目标)/混合),你会为每种颜色执行此操作:'red' => intval(255.0 - (255.0 - $topColor['red']) / $baseColor['red']))
以上是关于如何将 2 个图像与 PHP(GD-GD2 库)混合,如乘法、颜色燃烧、颜色道奇等的主要内容,如果未能解决你的问题,请参考以下文章