You are here

function image_gd_roundedcorners in ImageCache Actions 7

Same name and namespace in other branches
  1. 8 canvasactions/rounded_corners.inc \image_gd_roundedcorners()

Trim rounded corners off an image, using an anti-aliasing algorithm.

Implementation of hook_image()

Note, this is not image toolkit-agnostic yet! It just assumes GD. We can abstract it out once we have something else to abstract to. In the meantime just don't.

'handcoded' rounded corners logic contributed by donquixote 2009-08-31

Parameters

$image:

$action:

File

canvasactions/rounded_corners.inc, line 132
Routines for rounded corners

Code

function image_gd_roundedcorners($image, $action) {

  // Read settings.
  $width = $image->info['width'];
  $height = $image->info['height'];
  $radius = $action['radius'];
  $independent_corners = !empty($action['independent_corners_set']['independent_corners']);
  $corners = array(
    'tl',
    'tr',
    'bl',
    'br',
  );
  $im =& $image->resource;

  // Prepare drawing on the alpha channel.
  imagesavealpha($im, TRUE);
  imagealphablending($im, FALSE);
  foreach ($corners as $key) {
    if ($independent_corners && isset($action['independent_corners_set']['radii'][$key])) {
      $r = $action['independent_corners_set']['radii'][$key];
    }
    else {

      // Use the all-the-same radius setting.
      $r = $radius;
    }

    // key can be 'tl', 'tr', 'bl', 'br'.
    $is_bottom = $key[0] == 'b';
    $is_right = $key[1] == 'r';

    // dx and dy are in "continuous coordinates",
    // and mark the distance of the pixel middle to the image border.
    for ($dx = 0.5; $dx < $r; ++$dx) {
      for ($dy = 0.5; $dy < $r; ++$dy) {

        // ix and iy are in discrete pixel indices,
        // counting from the top left
        $ix = floor($is_right ? $width - $dx : $dx);
        $iy = floor($is_bottom ? $height - $dy : $dy);

        // Color lookup at ($ix, $iy).
        $color_ix = imagecolorat($im, $ix, $iy);
        $color = imagecolorsforindex($im, $color_ix);

        // Do not process opacity if transparency is 100%. Just jump...
        // Opacity is always 0 on a transparent source pixel.
        if ($color['alpha'] != 127) {
          $opacity = _canvasactions_roundedcorners_pixel_opacity($dx, $dy, $r);
          if ($opacity >= 1) {

            // we can finish this row,
            // all following pixels will be fully opaque.
            break;
          }
          if (isset($color['alpha'])) {
            $color['alpha'] = 127 - round($opacity * (127 - $color['alpha']));
          }
          else {
            $color['alpha'] = 127 - round($opacity * 127);
          }

          // Value should not be more than 127, and not less than 0.
          $color['alpha'] = $color['alpha'] > 127 ? 127 : ($color['alpha'] < 0 ? 0 : $color['alpha']);
        }
        $color_ix = imagecolorallocatealpha($im, $color['red'], $color['green'], $color['blue'], $color['alpha']);
        imagesetpixel($im, $ix, $iy, $color_ix);
      }
    }
  }
  return TRUE;
}