views:

485

answers:

2

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.

  • 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?).

  • 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?
+2  A: 

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:

// "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);
Greg
Cheers, that seemed to work, but I had to add imagecolortransparent($img, $c); as well, does that sound right?
MSpreij
Hmm not for PNG... kinda strange. I don't think I've created a palletted PNG through GD before so maybe you need it for that? I would be surprised, but then again anything is possible!
Greg
Try using imagesavealpha($img, true); instead.
Greg
I'm just displaying them in the webpage (they're graphs with live data). It may have something to do with the source image or the way they're loaded - anyway, it's doing what I wanted now :-)
MSpreij
A: 

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