如何选择要在图像中透明的颜色?

3

第一个问题,请温柔一点 ;-)

我编写了一个图像类,使得简单的事情(矩形、文本)更容易,基本上是 PHP 图像函数的一堆包装器方法。
现在我想做的是允许用户定义选择区域,并且只影响所选区域下面的图像操作。我想通过将图像复制到 imgTwo 并从中删除所选区域来实现此目的,像往常一样对原始图像进行以下图像操作,然后在调用 $img->deselect() 时将 imgTwo 复制回原始图像并销毁该副本。

  • 这是最好的方法吗?显然,在所选区域内定义未选择的区域会很棘手,但是我现在可以接受 :)

然后,我从副本中擦除选择的方法是使用透明颜色绘制矩形,这是有效的 - 但我无法弄清楚如何选择颜色并确保它不出现在图像的其他部分。这个应用程序中的输入图像是真彩 PNG,因此没有带有颜色索引的调色板(我认为?)。

  • 肯定有比收集每个单独像素的颜色并找到不在 $existing_colours 数组中出现的颜色更好的方法,对吧?
2个回答

3
PNG透明度与GIF透明度不同 - 您不需要定义特定的颜色作为透明色。 只需使用imagecolorallocatealpha()并确保您设置了imagealphablending()false:
// "0, 0, 0" can be anything; 127 = completely transparent
$c = imagecolorallocatealpha($img, 0, 0, 0, 127);

// Set this to be false to overwrite the rectangle instead of drawing on top of it
imagealphablending($img, false);

imagefilledrectangle($img, $x, $y, $width - 1, $height - 1, $c);

好的,看起来它有效了,但是我还需要加上imagecolortransparent($img, $c)操作,这样对吗? - MSpreij
嗯,不适用于 PNG……有点奇怪。我想我以前没有通过 GD 创建过索引色 PNG,所以也许你需要它?我会感到惊讶,但再怎么说也有可能! - Greg
尝试使用imagesavealpha($img, true);代替。 - Greg
1
我只是在网页上显示它们(它们是带有实时数据的图形)。这可能与源图像或加载方式有关 - 不管怎样,现在它正在按照我的意愿进行。 - MSpreij

0
代码最终看起来像这样:
# -- select($x, $y, $x2, $y2)
function select($x, $y, $x2, $y2) {
  if (! $this->selected) { // first selection. create new image resource, copy current image to it, set transparent color
    $this->copy = new MyImage($this->x, $this->y); // tmp image resource
    imagecopymerge($this->copy->img, $this->img, 0, 0, 0, 0, $this->x, $this->y, 100); // copy the original to it
    $this->copy->trans = imagecolorallocatealpha($this->copy->img, 0, 0, 0, 127); // yep, it's see-through black
    imagealphablending($this->copy->img, false);                                  // (with alphablending on, drawing transparent areas won't really do much..)
    imagecolortransparent($this->copy->img, $this->copy->trans);                  // somehow this doesn't seem to affect actual black areas that were already in the image (phew!)
    $this->selected = true;
  }
  $this->copy->rect($x, $y, $x2, $y2, $this->copy->trans, 1); // Finally erase the defined area from the copy
}

# -- deselect()
function deselect() {
  if (! $this->selected) return false;
  if (func_num_args() == 4) { // deselect an area from the current selection
    list($x, $y, $x2, $y2) = func_get_args();
    imagecopymerge($this->copy->img, $this->img, $x, $y, $x, $y, $x2-$x, $y2-$y, 100);
  }else{ // deselect everything, draw the perforated copy back over the original
    imagealphablending($this->img, true);
    imagecopymerge($this->img, $this->copy->img, 0, 0, 0, 0, $this->x, $this->y, 100); // copy the copy back
    $this->copy->__destruct();
    $this->selected = false;
  }
}

对于那些好奇的人,这里是两个类:

http://dev.expocom.nl/functions.php?id=104 (image.class.php)
http://dev.expocom.nl/functions.php?id=171 (MyImage.class.php extends image.class.php)

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接