如何选择一种颜色使图像透明?

时间:2023-01-16 00:33:28

First question, please be gentle ;-)

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

I've written an image class that makes simple things (rectangles, text) a bit easier, basically a bunch of wrapper methods for PHP's image functions.
What I'm trying to do now is to allow the user to define a selection, and have the following image operations only affect the selected area. I figured I'd do this by copying the image to imgTwo and deleting the selected area from it, do the following image operations on the original as usual, then when $img->deselect() is called, copy imgTwo back to the original, and destroy the copy.

我编写了一个图像类,它使简单的东西(矩形,文本)变得更容易,基本上是PHP的图像函数的一堆包装方法。我现在要做的是允许用户定义选择,并使以下图像操作仅影响所选区域。我想通过将图像复制到imgTwo并从中删除所选区域来做到这一点,像往常一样在原件上执行以下图像操作,然后当调用$ img-> deselect()时,将imgTwo复制回原始图像,并销毁副本。

  • is this the best way? obviously it will be tricky to define deselected areas within a selected area but I can live with that for now :)
  • 这是最好的方法吗?显然,在选定区域内定义取消选择的区域会很棘手,但我现在可以忍受这个:)

Then, the way I'm erasing the selection from the copy is by drawing a rectangle in a transparent color, which is working - but I can't figure out how to choose that color while being sure it doesn't occur in the rest of the image. The input images in this application are true color PNGs, so no palette with color indexes (I think?).

然后,我从副本中删除选择的方式是通过绘制透明颜色的矩形,这是有效的 - 但我无法弄清楚如何选择该颜色,同时确保它不会发生在其他颜色图像。此应用程序中的输入图像是真彩色PNG,因此没有带颜色索引的调色板(我认为?)。

  • There has to be a better way than to collect the colours of each individual pixel and then finding a color that doesn't appear in the $existing_colours array .. right?
  • 必须有一个更好的方法,而不是收集每个像素的颜色,然后找到$ existing_colours数组中没有出现的颜色..对吧?

2 个解决方案

#1


PNG transparency works differently to GIF transparency - you don't need to define a particular colour as transparent. Just use imagecolorallocatealpha() and make sure you've set imagealphablending() to false:

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

#2


The code ended up looking like this:

代码最终看起来像这样:

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

For those curious, here are the two classes:

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

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)

#1


PNG transparency works differently to GIF transparency - you don't need to define a particular colour as transparent. Just use imagecolorallocatealpha() and make sure you've set imagealphablending() to false:

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

#2


The code ended up looking like this:

代码最终看起来像这样:

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

For those curious, here are the two classes:

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

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)