You are here

function png_color2alpha in ImageCache Actions 7

Same name and namespace in other branches
  1. 8 coloractions/transparency.inc \png_color2alpha()
  2. 5.3 transparency.inc \png_color2alpha()
  3. 5.2 transparency.inc \png_color2alpha()
  4. 6.2 coloractions/transparency.inc \png_color2alpha()
  5. 6 transparency.inc \png_color2alpha()

This achieves a tonal effect by converting the images combined tone and existing transparency into one shade value. This is then used as the ALPHA transparency for that pixel, while the whole thing is coloured the same shade. Images 'grey toned' in this manner should sit smoothly on any background.

With no color set, use the existing hue.

To save a partially transparent image, the image resource must be switched to PNG. ... or maybe not. Just flatten it yourself, or switch the format yourself. This hack would produce side effects otherwise.

This algorithm runs maths per-pixel, and therefore is incredibly much more inefficient than any native routine. Will kill the server on large images.

Parameters

stdClass $image:

string $color:

float $opacity: between 0 transparent and 1 solid.

Return value

bool true on success, false otherwise.

1 call to png_color2alpha()
coloractions_alpha_effect in coloractions/transparency.inc
Image effect callback for the alpha effect.

File

coloractions/transparency.inc, line 189
Helper functions for the alpha effect.

Code

function png_color2alpha(stdClass $image, $color, $opacity = NULL) {
  $info = $image->info;
  if (!$info) {
    return FALSE;
  }
  $im1 = $image->resource;
  imagesavealpha($im1, TRUE);
  imagealphablending($im1, FALSE);
  if ($color) {
    $background = imagecache_actions_hex2rgba($color);
  }
  $width = imagesx($im1);
  $height = imagesy($im1);
  if ($width * $height > 1200 * 1200) {
    watchdog('imagecache_actions', __FUNCTION__ . " on {$image->source}. Image is TOO BIG to run the per-pixel algorithm. Aborting.");
    return FALSE;
  }
  for ($i = 0; $i < $height; $i++) {

    //this loop traverses each row in the image
    for ($j = 0; $j < $width; $j++) {

      //this loop traverses each pixel of each row

      // Get the color & alpha info of the current pixel.
      $retrieved_color = imagecolorat($im1, $j, $i);

      // an index
      $rgba_array = imagecolorsforindex($im1, $retrieved_color);
      $alpha = 127;

      // Calculate the total shade value of this pixel.
      // If the rule sets a color, then the darkness of the existing
      // pixel will define the desired alpha value.
      if ($color) {
        $lightness = ($rgba_array['red'] + $rgba_array['green'] + $rgba_array['blue']) / 3;

        // Need to flip the numbers around before doing maths.

        //$opacity = 1-($rgba_array['alpha']/127);

        //$darkness = 1-($lightness/256); // 0 is white, 1 is black

        //$visibility = $darkness * $opacity;

        //$alpha = (1-$visibility) * 127;
        $alpha = (1 - (1 - $lightness / 256) * (1 - $rgba_array['alpha'] / 127)) * 127;
      }

      // If color is NOT set, then the existing color is passed though, only
      // made somewhat transparent.
      if (!$color) {
        $background = $rgba_array;
      }
      if ($opacity) {

        // It's a user-defined alpha value.
        $alpha = $alpha * $opacity;
      }

      // Paint the pixel.

      /** @noinspection PhpUndefinedVariableInspection */
      $color_to_paint = imagecolorallocatealpha($image->resource, $background['red'], $background['green'], $background['blue'], $alpha);
      imagesetpixel($image->resource, $j, $i, $color_to_paint);
    }
  }
  return TRUE;
}