public function create(BoxInterface $size, ColorInterface $color = null) { $width = $size->getWidth(); $height = $size->getHeight(); if ($color === null) { $palette = self::$rgb; $color = '#ffffff'; $alpha = 0; } else { $palette = $color->getPalette(); $alpha = $color->getAlpha() / 100; } try { $pixel = new \GmagickPixel((string) $color); $pixel->setcolorvalue(\Gmagick::COLOR_OPACITY, $alpha); // does nothing as of Gmagick 1.1.7RC2. Background will be fully opaque. $magick = new \Gmagick(); $magick->newimage($width, $height, $pixel->getcolor(false)); $magick->setimagecolorspace(\Gmagick::COLORSPACE_TRANSPARENT); $magick->setimagebackgroundcolor($pixel); return new RImage($magick, $palette, self::$emptyBag, array($width, $height)); } catch (\Exception $e) { throw new \Imagine\Exception\RuntimeException("Gmagick: could not create empty image. {$e->getMessage()}", $e->getCode(), $e); } }
/** * {@inheritdoc} */ public function create(BoxInterface $size, ColorInterface $color = null) { $width = $size->getWidth(); $height = $size->getHeight(); $palette = null !== $color ? $color->getPalette() : new RGB(); $color = null !== $color ? $color : $palette->color('fff'); try { $gmagick = new \Gmagick(); // Gmagick does not support creation of CMYK GmagickPixel // see https://bugs.php.net/bug.php?id=64466 if ($color instanceof CMYKColor) { $switchPalette = $palette; $palette = new RGB(); $pixel = new \GmagickPixel($palette->color((string) $color)); } else { $switchPalette = null; $pixel = new \GmagickPixel((string) $color); } if ($color->getPalette()->supportsAlpha() && $color->getAlpha() < 100) { throw new NotSupportedException('alpha transparency is not supported'); } $gmagick->newimage($width, $height, $pixel->getcolor(false)); $gmagick->setimagecolorspace(\Gmagick::COLORSPACE_TRANSPARENT); $gmagick->setimagebackgroundcolor($pixel); $image = new Image($gmagick, $palette, new MetadataBag()); if ($switchPalette) { $image->usePalette($switchPalette); } return $image; } catch (\GmagickException $e) { throw new RuntimeException('Could not create empty image', $e->getCode(), $e); } }
/** * (non-PHPdoc) * @see Imagine\Image\ImagineInterface::create() */ public function create(BoxInterface $size, Color $color = null) { $width = $size->getWidth(); $height = $size->getHeight(); $color = null !== $color ? $color : new Color('fff'); $gmagick = new \Gmagick(); $pixel = new \GmagickPixel((string) $color); if ($color->getAlpha() > 0) { // TODO: implement support for transparent background throw new RuntimeException('alpha transparency not implemented'); } $gmagick->newimage($width, $height, $pixel->getcolor(false)); $gmagick->setimagecolorspace(\Gmagick::COLORSPACE_TRANSPARENT); // this is needed to propagate transparency $gmagick->setimagebackgroundcolor($pixel); return new Image($gmagick); }
public function transform($operation, $parameters) { if ($this->properties["mimetype"] == "image/tilepic") { return false; } # no transformations for Tilepic if (!$this->handle) { return false; } if (!$this->info["TRANSFORMATIONS"][$operation]) { # invalid transformation $this->postError(1655, _t("Invalid transformation %1", $operation), "WLPlugGmagick->transform()"); return false; } # get parameters for this operation $sparams = $this->info["TRANSFORMATIONS"][$operation]; $w = $parameters["width"]; $h = $parameters["height"]; $cw = $this->get("width"); $ch = $this->get("height"); if ((bool) $this->properties['no_upsampling']) { $w = min($cw, round($w)); $h = min($ch, round($h)); } $do_crop = 0; try { switch ($operation) { # ----------------------- case 'ANNOTATE': $d = new GmagickDraw(); if ($parameters['font']) { try { $d->setfont($parameters['font']); } catch (Exception $e) { $this->postError(1655, _t("Couldn't set font to %1. Gmagick error message: %2", $parameters['font'], $e->getMessage()), "WLPlugGmagick->transform()"); break; } } $size = $parameters['size'] > 0 ? $parameters['size'] : 18; $d->setfontsize($size); $inset = $parameters['inset'] > 0 ? $parameters['inset'] : 0; $pw = new GmagickPixel(); $pw->setcolor($parameters['color'] ? $parameters['color'] : "black"); $d->setfillcolor($pw); switch ($parameters['position']) { default: break; } $this->handle->annotateimage($d, $inset, $size + $inset, 0, $parameters['text']); break; # ----------------------- # ----------------------- case 'WATERMARK': if (!file_exists($parameters['image'])) { break; } # gmagick can't handle opacity when compositing images #$vn_opacity_setting = $parameters['opacity']; #if (($vn_opacity_setting < 0) || ($vn_opacity_setting > 1)) { # $vn_opacity_setting = 0.5; #} if (($vn_watermark_width = $parameters['width']) < 10) { $vn_watermark_width = $cw / 2; } if (($vn_watermark_height = $parameters['height']) < 10) { $vn_watermark_height = $ch / 2; } switch ($parameters['position']) { case 'north_east': $vn_watermark_x = $cw - $vn_watermark_width; $vn_watermark_y = 0; break; case 'north_west': $vn_watermark_x = 0; $vn_watermark_y = 0; break; case 'north': $vn_watermark_x = ($cw - $vn_watermark_width) / 2; $vn_watermark_y = 0; break; case 'south_east': $vn_watermark_x = $cw - $vn_watermark_width; $vn_watermark_y = $ch - $vn_watermark_height; break; case 'south': $vn_watermark_x = ($cw - $vn_watermark_width) / 2; $vn_watermark_y = $ch - $vn_watermark_height; break; case 'center': $vn_watermark_x = ($cw - $vn_watermark_width) / 2; $vn_watermark_y = ($ch - $vn_watermark_height) / 2; break; case 'south_west': default: $vn_watermark_x = $cw - $vn_watermark_width; $vn_watermark_y = $ch - $vn_watermark_height; break; } try { $w = new Gmagick($parameters['image']); $this->setResourceLimits($w); } catch (Exception $e) { $this->postError(1610, _t("Couldn't load watermark image at %1", $parameters['image']), "WLPlugGmagick->transform:WATERMARK()"); return false; } $w->scaleimage($vn_watermark_width, $vn_watermark_height); $this->handle->compositeimage($w, 1, $vn_watermark_x, $vn_watermark_y); break; # ----------------------- # ----------------------- case 'SCALE': $aa = $parameters["antialiasing"]; if ($aa <= 0) { $aa = 0; } switch ($parameters["mode"]) { # ---------------- case "width": $scale_factor = $w / $cw; $h = $ch * $scale_factor; break; # ---------------- # ---------------- case "height": $scale_factor = $h / $ch; $w = $cw * $scale_factor; break; # ---------------- # ---------------- case "bounding_box": $scale_factor_w = $w / $cw; $scale_factor_h = $h / $ch; $w = $cw * ($scale_factor_w < $scale_factor_h ? $scale_factor_w : $scale_factor_h); $h = $ch * ($scale_factor_w < $scale_factor_h ? $scale_factor_w : $scale_factor_h); break; # ---------------- # ---------------- case "fill_box": $crop_from = $parameters["crop_from"]; if (!in_array($crop_from, array('center', 'north_east', 'north_west', 'south_east', 'south_west', 'random'))) { $crop_from = ''; } $scale_factor_w = $w / $cw; $scale_factor_h = $h / $ch; $w = $cw * ($scale_factor_w > $scale_factor_h ? $scale_factor_w : $scale_factor_h); $h = $ch * ($scale_factor_w > $scale_factor_h ? $scale_factor_w : $scale_factor_h); $do_fill_box_crop = true; break; # ---------------- } $w = round($w); $h = round($h); if ($w > 0 && $h > 0) { $crop_w_edge = $crop_h_edge = 0; if (preg_match("/^([\\d]+)%\$/", $parameters["trim_edges"], $va_matches)) { $crop_w_edge = ceil(intval($va_matches[1]) / 100 * $w); $crop_h_edge = ceil(intval($va_matches[1]) / 100 * $h); } else { if (isset($parameters["trim_edges"]) && intval($parameters["trim_edges"]) > 0) { $crop_w_edge = $crop_h_edge = intval($parameters["trim_edges"]); } } if (!$this->handle->resizeimage($w + $crop_w_edge * 2, $h + $crop_h_edge * 2, Gmagick::FILTER_CUBIC, $aa)) { $this->postError(1610, _t("Error during resize operation"), "WLPlugGmagick->transform()"); return false; } if ($do_fill_box_crop) { // use face detection info to intelligently crop if (is_array($this->properties['faces']) && sizeof($this->properties['faces'])) { $va_info = array_shift($this->properties['faces']); $crop_from_offset_x = ceil($va_info['x'] * ($scale_factor_w > $scale_factor_h ? $scale_factor_w : $scale_factor_h)); $crop_from_offset_x -= ceil(0.15 * $parameters["width"]); // since face will be tightly cropped give it some room $crop_from_offset_y = ceil($va_info['y'] * ($scale_factor_w > $scale_factor_h ? $scale_factor_w : $scale_factor_h)); $crop_from_offset_y -= ceil(0.15 * $parameters["height"]); // since face will be tightly cropped give it some room // Don't try to crop beyond image boundaries, you just end up scaling the image, often awkwardly if ($crop_from_offset_x > $w - $parameters["width"]) { $crop_from_offset_x = 0; } if ($crop_from_offset_y > $h - $parameters["height"]) { $crop_from_offset_y = 0; } if ($crop_from_offset_x < 0) { $crop_from_offset_x = 0; } if ($crop_from_offset_y < 0) { $crop_from_offset_y = 0; } } else { switch ($crop_from) { case 'north_west': $crop_from_offset_y = 0; $crop_from_offset_x = $w - $parameters["width"]; break; case 'south_east': $crop_from_offset_x = 0; $crop_from_offset_y = $h - $parameters["height"]; break; case 'south_west': $crop_from_offset_x = $w - $parameters["width"]; $crop_from_offset_y = $h - $parameters["height"]; break; case 'random': $crop_from_offset_x = rand(0, $w - $parameters["width"]); $crop_from_offset_y = rand(0, $h - $parameters["height"]); break; case 'north_east': $crop_from_offset_x = $crop_from_offset_y = 0; break; case 'center': default: $crop_from_offset_x = $crop_from_offset_y = 0; // Get image center $vn_center_x = caGetOption('_centerX', $parameters, 0.5); $vn_center_y = caGetOption('_centerY', $parameters, 0.5); if ($w > $parameters["width"]) { $crop_from_offset_x = ceil($w * $vn_center_x) - $parameters["width"] / 2; if ($crop_from_offset_x + $parameters["width"] > $w) { $crop_from_offset_x = $w - $parameters["width"]; } if ($crop_from_offset_x < 0) { $crop_from_offset_x = 0; } } else { if ($h > $parameters["height"]) { $crop_from_offset_y = ceil($h * $vn_center_y) - $parameters["height"] / 2; if ($crop_from_offset_y + $parameters["height"] > $h) { $crop_from_offset_y = $h - $parameters["height"]; } if ($crop_from_offset_y < 0) { $crop_from_offset_y = 0; } } } break; } } if (!$this->handle->cropimage($parameters["width"], $parameters["height"], $crop_w_edge + $crop_from_offset_x, $crop_h_edge + $crop_from_offset_y)) { $this->postError(1610, _t("Error during crop operation"), "WLPlugGmagick->transform()"); return false; } $this->properties["width"] = $parameters["width"]; $this->properties["height"] = $parameters["height"]; } else { if ($crop_w_edge || $crop_h_edge) { if (!$this->handle->cropimage($w, $h, $crop_w_edge, $crop_h_edge)) { $this->postError(1610, _t("Error during crop operation"), "WLPlugGmagick->transform()"); return false; } } $this->properties["width"] = $w; $this->properties["height"] = $h; } } break; # ----------------------- # ----------------------- case "ROTATE": $angle = $parameters["angle"]; if ($angle > -360 && $angle < 360) { if (!$this->handle->rotateimage("#FFFFFF", $angle)) { $this->postError(1610, _t("Error during image rotate"), "WLPlugGmagick->transform():ROTATE"); return false; } } break; # ----------------------- # ----------------------- case "DESPECKLE": if (!$this->handle->despeckleimage()) { $this->postError(1610, _t("Error during image despeckle"), "WLPlugGmagick->transform:DESPECKLE()"); return false; } break; # ----------------------- # ----------------------- case "MEDIAN": $radius = $parameters["radius"]; if ($radius < 0.1) { $radius = 1; } if (!$this->handle->medianfilterimage($radius)) { $this->postError(1610, _t("Error during image median filter"), "WLPlugGmagick->transform:MEDIAN()"); return false; } break; # ----------------------- # ----------------------- case "SHARPEN": $radius = $parameters["radius"]; if ($radius < 0.1) { $radius = 1; } $sigma = $parameters["sigma"]; if ($sigma < 0.1) { $sigma = 1; } if (!$this->handle->sharpenImage($radius, $sigma)) { $this->postError(1610, _t("Error during image sharpen"), "WLPlugGmagick->transform:SHARPEN()"); return false; } break; # ----------------------- # ----------------------- case "UNSHARPEN_MASK": # noop break; # ----------------------- # ----------------------- case "SET": while (list($k, $v) = each($parameters)) { $this->set($k, $v); } break; # ----------------------- } return 1; } catch (Exception $e) { $this->postError(1610, _t("Gmagick exception"), "WLPlugGmagick->transform"); return false; } }
/** * Gets specifically formatted color string from Color instance * * @param ColorInterface $color * * @return string */ private function getColor(ColorInterface $color) { if (!$color->isOpaque()) { throw new InvalidArgumentException('Gmagick doesn\'t support transparency'); } $pixel = new \GmagickPixel((string) $color); $pixel->setColorValue(\Gmagick::COLOR_OPACITY, number_format(abs(round($color->getAlpha() / 100, 1)), 1)); return $pixel; }
/** * Returns a color given a pixel, depending the Palette context * * Note : this method is public for PHP 5.3 compatibility * * @param \GmagickPixel $pixel * * @return ColorInterface * * @throws InvalidArgumentException In case a unknown color is requested */ public function pixelToColor(\GmagickPixel $pixel) { static $colorMapping = array(ColorInterface::COLOR_RED => \Gmagick::COLOR_RED, ColorInterface::COLOR_GREEN => \Gmagick::COLOR_GREEN, ColorInterface::COLOR_BLUE => \Gmagick::COLOR_BLUE, ColorInterface::COLOR_CYAN => \Gmagick::COLOR_CYAN, ColorInterface::COLOR_MAGENTA => \Gmagick::COLOR_MAGENTA, ColorInterface::COLOR_YELLOW => \Gmagick::COLOR_YELLOW, ColorInterface::COLOR_KEYLINE => \Gmagick::COLOR_BLACK, ColorInterface::COLOR_GRAY => \Gmagick::COLOR_RED); if ($this->palette->supportsAlpha()) { try { $alpha = (int) round($pixel->getcolorvalue(\Gmagick::COLOR_ALPHA) * 100); } catch (\GmagickPixelException $e) { $alpha = null; } } else { $alpha = null; } $palette = $this->palette(); return $this->palette->color(array_map(function ($color) use($palette, $pixel, $colorMapping) { if (!isset($colorMapping[$color])) { throw new InvalidArgumentException(sprintf('Color %s is not mapped in Gmagick', $color)); } $multiplier = 255; if ($palette->name() === PaletteInterface::PALETTE_CMYK) { $multiplier = 100; } return $pixel->getcolorvalue($colorMapping[$color]) * $multiplier; }, $this->palette->pixelDefinition()), $alpha); }
/** * Gets specifically formatted color string from Color instance * * @param Imagine\Image\Color $color * * @return string */ private function getColor(Color $color) { $pixel = new \GmagickPixel((string) $color); $pixel->setColorValue(\Gmagick::COLOR_OPACITY, number_format(abs(round($color->getAlpha() / 100, 1)), 1)); return $pixel; }