public function validate(Image $origImage) { if ($origImage->getWidth() !== $origImage->getHeight()) { throw new InvalidRatioException('Image should be a square'); } if ($origImage->getWidth() < self::MIN_SIZE) { throw new ImageTooSmallException(sprintf('Image should be more than %s px', self::MIN_SIZE)); } }
/** * Perform shape image manipulation. * @param Image $image The source image. * @return Image The manipulated image. */ public function run(Image $image) { $shape = $this->getShape(); if ($shape !== null) { $width = $image->getWidth(); $height = $image->getHeight(); $min = min($width, $height); $outerRadius = $min / 2; $mask = null; if ($shape === 'ellipse') { $mask = $this->makeEllipseMaskImage($image, $width, $height); } if ($shape === 'triangle-180') { // Triangle upside down $mask = $this->makeShapeMaskImage($image, $width, $height, 3, $outerRadius, $outerRadius, pi()); } if ($shape === 'triangle') { // Triangle normal $mask = $this->makeShapeMaskImage($image, $width, $height, 3, $outerRadius, $outerRadius, 0); } if ($shape === 'square') { // Square tilted 45 degrees $mask = $this->makeShapeMaskImage($image, $width, $height, 4, $outerRadius, $outerRadius, 0); } if ($shape === 'pentagon-180') { // Pentagon tilted upside down $mask = $this->makeShapeMaskImage($image, $width, $height, 5, $outerRadius, $outerRadius, pi()); } if ($shape === 'pentagon') { // Pentagon normal $mask = $this->makeShapeMaskImage($image, $width, $height, 5, $outerRadius, $outerRadius, 0); } if ($shape === 'star-3') { // 3 point star $mask = $this->makeShapeMaskImage($image, $width, $height, 3, $outerRadius, $outerRadius * 0.191, 0); } if ($shape === 'star-4') { // 4 point star $mask = $this->makeShapeMaskImage($image, $width, $height, 4, $outerRadius, $outerRadius * 0.382, 0); } if ($shape === 'star' || $shape === 'star-5') { // 5 point star $mask = $this->makeShapeMaskImage($image, $width, $height, 5, $outerRadius, $outerRadius * 0.382, 0); } if ($shape === 'circle') { $mask = $this->makeCircleMaskImage($image, $width, $height); } if ($mask !== null) { $image = $image->mask($mask, false); if ($shape !== 'ellipse') { $min = min($width, $height); $image->crop($min, $min); // TODO Should we trim it? $image->trim(); } } } return $image; }
/** * Resizes image boundaries * * @param \Intervention\Image\Image $image * @return boolean */ public function execute($image) { $width = $this->argument(0)->type('digit')->required()->value(); $height = $this->argument(1)->type('digit')->required()->value(); $anchor = $this->argument(2)->value('center'); $relative = $this->argument(3)->type('boolean')->value(); $bgcolor = $this->argument(4)->value(); $original_width = $image->getWidth(); $original_height = $image->getHeight(); // check of only width or height is set $width = is_null($width) ? $original_width : intval($width); $height = is_null($height) ? $original_height : intval($height); // check on relative width/height if ($relative) { $width = $original_width + $width; $height = $original_height + $height; } // check for negative width/height $width = $width <= 0 ? $width + $original_width : $width; $height = $height <= 0 ? $height + $original_height : $height; // create new canvas $canvas = $image->getDriver()->newImage($width, $height, $bgcolor); // set copy position $canvas_size = $canvas->getSize()->align($anchor); $image_size = $image->getSize()->align($anchor); $canvas_pos = $image_size->relativePosition($canvas_size); $image_pos = $canvas_size->relativePosition($image_size); if ($width <= $original_width) { $dst_x = 0; $src_x = $canvas_pos->x; $src_w = $canvas_size->width; } else { $dst_x = $image_pos->x; $src_x = 0; $src_w = $original_width; } if ($height <= $original_height) { $dst_y = 0; $src_y = $canvas_pos->y; $src_h = $canvas_size->height; } else { $dst_y = $image_pos->y; $src_y = 0; $src_h = $original_height; } // make image area transparent to keep transparency // even if background-color is set $transparent = imagecolorallocatealpha($canvas->getCore(), 255, 255, 255, 127); imagealphablending($canvas->getCore(), false); // do not blend / just overwrite imagefilledrectangle($canvas->getCore(), $dst_x, $dst_y, $dst_x + $src_w - 1, $dst_y + $src_h - 1, $transparent); // copy image into new canvas imagecopy($canvas->getCore(), $image->getCore(), $dst_x, $dst_y, $src_x, $src_y, $src_w, $src_h); // set new core to canvas $image->setCore($canvas->getCore()); return true; }
/** * Applies a pixelation effect to a given image * * @param \Intervention\Image\Image $image * @return boolean */ public function execute($image) { $size = $this->argument(0)->type('digit')->value(10); $width = $image->getWidth(); $height = $image->getHeight(); $image->getCore()->scaleImage(max(1, $width / $size), max(1, $height / $size)); $image->getCore()->scaleImage($width, $height); return true; }
protected function text() { if ($this->text) { $x = $this->fontPadding; $y = $this->fontPadding; switch ($this->fontAlignHorizontal) { case 'center': $x = $this->image->getWidth() / 2; $this->fontAlignHorizontal = 'center'; break; case 'right': $x = $this->image->getWidth() - 3 - $this->fontPadding; $this->fontAlignHorizontal = 'right'; break; } switch ($this->fontAlignVertical) { case 'middle': $y = $this->image->getHeight() / 2 + $this->fontPadding; $this->fontAlignVertical = 'middle'; break; case 'bottom': $y = $this->image->getHeight() - 4 - $this->fontPadding; break; } $this->image->text($this->text, $x, $y, function ($font) { /* @var $font \Intervention\Image\Imagick\Font */ $fontType = $_ENV['base_path'] . 'fonts' . DIRECTORY_SEPARATOR . $this->font . ".ttf"; $font->file($fontType); $font->color('#' . $this->fontColor); $font->size($this->fontSize); $font->valign($this->fontAlignVertical); $font->align($this->fontAlignHorizontal); if ($this->fontFit == 'max') { $maxWidth = $this->image->getWidth(); $fontSize = $this->fontSize; while (true) { $font->size($fontSize); $metrics = $this->getResourceSize($fontType, $this->text, $fontSize, 0); if ($metrics['width'] <= $maxWidth) { break; } $fontSize = (double) $fontSize - 0.1; if ($fontSize <= 0) { break; } } } }); } }
/** * Fills image with color or pattern * * @param \Intervention\Image\Image $image * @return boolean */ public function execute($image) { $filling = $this->argument(0)->value(); $x = $this->argument(1)->type('digit')->value(); $y = $this->argument(2)->type('digit')->value(); $width = $image->getWidth(); $height = $image->getHeight(); $resource = $image->getCore(); try { // set image tile filling $source = new Decoder(); $tile = $source->init($filling); imagesettile($image->getCore(), $tile->getCore()); $filling = IMG_COLOR_TILED; } catch (\Intervention\Image\Exception\NotReadableException $e) { // set solid color filling $color = new Color($filling); $filling = $color->getInt(); } imagealphablending($resource, true); if (is_int($x) && is_int($y)) { // resource should be visible through transparency $base = $image->getDriver()->newImage($width, $height)->getCore(); imagecopy($base, $resource, 0, 0, 0, 0, $width, $height); // floodfill if exact position is defined imagefill($resource, $x, $y, $filling); // copy filled original over base imagecopy($base, $resource, 0, 0, 0, 0, $width, $height); // set base as new resource-core $image->setCore($base); imagedestroy($resource); } else { // fill whole image otherwise imagefilledrectangle($resource, 0, 0, $width - 1, $height - 1, $filling); } isset($tile) ? imagedestroy($tile->getCore()) : null; return true; }
/** * File's width * * @return int */ public function getWidth() { return $this->image->getWidth(); }
/** * Trims away parts of an image * * @param \Intervention\Image\Image $image * @return boolean */ public function execute($image) { $base = $this->argument(0)->type('string')->value(); $away = $this->argument(1)->value(); $tolerance = $this->argument(2)->type('numeric')->value(0); $feather = $this->argument(3)->type('numeric')->value(0); $width = $image->getWidth(); $height = $image->getHeight(); // default values $checkTransparency = false; // define borders to trim away if (is_null($away)) { $away = array('top', 'right', 'bottom', 'left'); } elseif (is_string($away)) { $away = array($away); } // lower border names foreach ($away as $key => $value) { $away[$key] = strtolower($value); } // define base color position switch (strtolower($base)) { case 'transparent': case 'trans': $checkTransparency = true; $base_x = 0; $base_y = 0; break; case 'bottom-right': case 'right-bottom': $base_x = $width - 1; $base_y = $height - 1; break; default: case 'top-left': case 'left-top': $base_x = 0; $base_y = 0; break; } // pick base color if ($checkTransparency) { $color = new Color(); // color will only be used to compare alpha channel } else { $color = $image->pickColor($base_x, $base_y, 'object'); } $top_x = 0; $top_y = 0; $bottom_x = $width; $bottom_y = $height; // search upper part of image for colors to trim away if (in_array('top', $away)) { for ($y = 0; $y < ceil($height / 2); $y++) { for ($x = 0; $x < $width; $x++) { $checkColor = $image->pickColor($x, $y, 'object'); if ($checkTransparency) { $checkColor->r = $color->r; $checkColor->g = $color->g; $checkColor->b = $color->b; } if ($color->differs($checkColor, $tolerance)) { $top_y = max(0, $y - $feather); break 2; } } } } // search left part of image for colors to trim away if (in_array('left', $away)) { for ($x = 0; $x < ceil($width / 2); $x++) { for ($y = $top_y; $y < $height; $y++) { $checkColor = $image->pickColor($x, $y, 'object'); if ($checkTransparency) { $checkColor->r = $color->r; $checkColor->g = $color->g; $checkColor->b = $color->b; } if ($color->differs($checkColor, $tolerance)) { $top_x = max(0, $x - $feather); break 2; } } } } // search lower part of image for colors to trim away if (in_array('bottom', $away)) { for ($y = $height - 1; $y >= floor($height / 2) - 1; $y--) { for ($x = $top_x; $x < $width; $x++) { $checkColor = $image->pickColor($x, $y, 'object'); if ($checkTransparency) { $checkColor->r = $color->r; $checkColor->g = $color->g; $checkColor->b = $color->b; } if ($color->differs($checkColor, $tolerance)) { $bottom_y = min($height, $y + 1 + $feather); break 2; } } } } // search right part of image for colors to trim away if (in_array('right', $away)) { for ($x = $width - 1; $x >= floor($width / 2) - 1; $x--) { for ($y = $top_y; $y < $bottom_y; $y++) { $checkColor = $image->pickColor($x, $y, 'object'); if ($checkTransparency) { $checkColor->r = $color->r; $checkColor->g = $color->g; $checkColor->b = $color->b; } if ($color->differs($checkColor, $tolerance)) { $bottom_x = min($width, $x + 1 + $feather); break 2; } } } } // trim parts of image return $this->modify($image, 0, 0, $top_x, $top_y, $bottom_x - $top_x, $bottom_y - $top_y, $bottom_x - $top_x, $bottom_y - $top_y); }
/** * Fills image with color or pattern * * @param \Intervention\Image\Image $image * @return boolean */ public function execute($image) { $filling = $this->argument(0)->value(); $x = $this->argument(1)->type('digit')->value(); $y = $this->argument(2)->type('digit')->value(); $imagick = $image->getCore(); try { // set image filling $source = new Decoder(); $filling = $source->init($filling); } catch (\Intervention\Image\Exception\NotReadableException $e) { // set solid color filling $filling = new Color($filling); } // flood fill if coordinates are set if (is_int($x) && is_int($y)) { // flood fill with texture if ($filling instanceof Image) { // create tile $tile = clone $image->getCore(); // mask away color at position $tile->transparentPaintImage($tile->getImagePixelColor($x, $y), 0, 0, false); // create canvas $canvas = clone $image->getCore(); // fill canvas with texture $canvas = $canvas->textureImage($filling->getCore()); // merge canvas and tile $canvas->compositeImage($tile, \Imagick::COMPOSITE_DEFAULT, 0, 0); // replace image core $image->setCore($canvas); // flood fill with color } elseif ($filling instanceof Color) { // create canvas with filling $canvas = new \Imagick(); $canvas->newImage($image->getWidth(), $image->getHeight(), $filling->getPixel(), 'png'); // create tile to put on top $tile = clone $image->getCore(); // mask away color at pos. $tile->transparentPaintImage($tile->getImagePixelColor($x, $y), 0, 0, false); // save alpha channel of original image $alpha = clone $image->getCore(); // merge original with canvas and tile $image->getCore()->compositeImage($canvas, \Imagick::COMPOSITE_DEFAULT, 0, 0); $image->getCore()->compositeImage($tile, \Imagick::COMPOSITE_DEFAULT, 0, 0); // restore alpha channel of original image $image->getCore()->compositeImage($alpha, \Imagick::COMPOSITE_COPYOPACITY, 0, 0); } } else { if ($filling instanceof Image) { // fill whole image with texture $image->setCore($image->getCore()->textureImage($filling->getCore())); } elseif ($filling instanceof Color) { // fill whole image with color $draw = new \ImagickDraw(); $draw->setFillColor($filling->getPixel()); $draw->rectangle(0, 0, $image->getWidth(), $image->getHeight()); $image->getCore()->drawImage($draw); } } return true; }
/** * Resizes image boundaries * * @param \Intervention\Image\Image $image * @return boolean */ public function execute($image) { $width = $this->argument(0)->type('digit')->required()->value(); $height = $this->argument(1)->type('digit')->required()->value(); $anchor = $this->argument(2)->value('center'); $relative = $this->argument(3)->type('boolean')->value(); $bgcolor = $this->argument(4)->value(); $original_width = $image->getWidth(); $original_height = $image->getHeight(); // check of only width or height is set $width = is_null($width) ? $original_width : intval($width); $height = is_null($height) ? $original_height : intval($height); // check on relative width/height if ($relative) { $width = $original_width + $width; $height = $original_height + $height; } // check for negative width/height $width = $width <= 0 ? $width + $original_width : $width; $height = $height <= 0 ? $height + $original_height : $height; // create new canvas $canvas = $image->getDriver()->newImage($width, $height, $bgcolor); // set copy position $canvas_size = $canvas->getSize()->align($anchor); $image_size = $image->getSize()->align($anchor); $canvas_pos = $image_size->relativePosition($canvas_size); $image_pos = $canvas_size->relativePosition($image_size); if ($width <= $original_width) { $dst_x = 0; $src_x = $canvas_pos->x; $src_w = $canvas_size->width; } else { $dst_x = $image_pos->x; $src_x = 0; $src_w = $original_width; } if ($height <= $original_height) { $dst_y = 0; $src_y = $canvas_pos->y; $src_h = $canvas_size->height; } else { $dst_y = $image_pos->y; $src_y = 0; $src_h = $original_height; } // make image area transparent to keep transparency // even if background-color is set $rect = new \ImagickDraw(); $fill = $canvas->pickColor(0, 0, 'hex'); $fill = $fill == '#ff0000' ? '#00ff00' : '#ff0000'; $rect->setFillColor($fill); $rect->rectangle($dst_x, $dst_y, $dst_x + $src_w - 1, $dst_y + $src_h - 1); $canvas->getCore()->drawImage($rect); $canvas->getCore()->transparentPaintImage($fill, 0, 0, false); $canvas->getCore()->setImageColorspace($image->getCore()->getImageColorspace()); foreach ($image as $frame) { // copy image into new canvas $frame->getCore()->cropImage($src_w, $src_h, $src_x, $src_y); $canvas->getCore()->compositeImage($frame->getCore(), \Imagick::COMPOSITE_DEFAULT, $dst_x, $dst_y); $canvas->getCore()->setImagePage(0, 0, 0, 0); $canvas->getCore()->setImageDelay($frame->getCore()->getImageDelay()); $canvas->getCore()->setImageIterations($frame->getCore()->getImageIterations()); // set new canvas as core $frame->getCore()->setImage($canvas->getCore()); } return true; }
/** * Trims away parts of an image * * @param \Intervention\Image\Image $image * @return boolean */ public function execute($image) { $base = $this->argument(0)->type('string')->value(); $away = $this->argument(1)->value(); $tolerance = $this->argument(2)->type('numeric')->value(0); $feather = $this->argument(3)->type('numeric')->value(0); $width = $image->getWidth(); $height = $image->getHeight(); $checkTransparency = false; // define borders to trim away if (is_null($away)) { $away = array('top', 'right', 'bottom', 'left'); } elseif (is_string($away)) { $away = array($away); } // lower border names foreach ($away as $key => $value) { $away[$key] = strtolower($value); } // define base color position switch (strtolower($base)) { case 'transparent': case 'trans': $checkTransparency = true; $base_x = 0; $base_y = 0; break; case 'bottom-right': case 'right-bottom': $base_x = $width - 1; $base_y = $height - 1; break; default: case 'top-left': case 'left-top': $base_x = 0; $base_y = 0; break; } // pick base color if ($checkTransparency) { $base_color = new Color(); // color will only be used to compare alpha channel } else { $base_color = $image->pickColor($base_x, $base_y, 'object'); } // trim on clone to get only coordinates $trimed = clone $image->getCore(); // add border to trim specific color $trimed->borderImage($base_color->getPixel(), 1, 1); // trim image $trimed->trimImage(65850 / 100 * $tolerance); // get coordinates of trim $imagePage = $trimed->getImagePage(); list($crop_x, $crop_y) = array($imagePage['x'] - 1, $imagePage['y'] - 1); // $trimed->setImagePage(0, 0, 0, 0); list($crop_width, $crop_height) = array($trimed->width, $trimed->height); // adjust settings if right should not be trimed if (!in_array('right', $away)) { $crop_width = $crop_width + ($width - ($width - $crop_x)); } // adjust settings if bottom should not be trimed if (!in_array('bottom', $away)) { $crop_height = $crop_height + ($height - ($height - $crop_y)); } // adjust settings if left should not be trimed if (!in_array('left', $away)) { $crop_width = $crop_width + $crop_x; $crop_x = 0; } // adjust settings if top should not be trimed if (!in_array('top', $away)) { $crop_height = $crop_height + $crop_y; $crop_y = 0; } // add feather $crop_width = min($width, $crop_width + $feather * 2); $crop_height = min($height, $crop_height + $feather * 2); $crop_x = max(0, $crop_x - $feather); $crop_y = max(0, $crop_y - $feather); // finally crop based on page $image->getCore()->cropImage($crop_width, $crop_height, $crop_x, $crop_y); $image->getCore()->setImagePage(0, 0, 0, 0); $trimed->destroy(); return true; }
protected function itemsHeader() { $this->image->rectangle(0, 1150, $this->image->getWidth(), 1265, function (AbstractShape $shape) { $shape->background($this->template->getColorEven()); }); $this->image->polygon([$this->image->getWidth(), 1150, $this->image->getWidth(), 1265, 2000, 1265, 2150, 1150], function (AbstractShape $shape) { $shape->background($this->template->getPrimaryColor()); }); $this->image->rectangle(0, 1265, $this->image->getWidth(), 1270, function (AbstractShape $shape) { $shape->background($this->template->getPrimaryColor()); }); $this->image->text(Strings::upper($this->translate('item')), 165, 1205, function (Font $font) { $font->color($this->template->getPrimaryColor()); $font->file($this->template->getFontBold()); $font->valign('center'); $font->align('center'); $font->size(37); }); $this->image->text(Strings::upper($this->translate('count')), 1250, 1205, function (Font $font) { $font->color($this->template->getPrimaryColor()); $font->file($this->template->getFontBold()); $font->valign('center'); $font->align('center'); $font->size(37); }); $this->image->text(Strings::upper($this->translate('pricePerItem')), 1650, 1205, function (Font $font) { $font->color($this->template->getPrimaryColor()); $font->file($this->template->getFontBold()); $font->valign('center'); $font->align('center'); $font->size(37); }); $this->image->text(Strings::upper($this->translate('total')), 2250, 1205, function (Font $font) { $font->color($this->template->getColorOdd()); $font->file($this->template->getFontBold()); $font->valign('center'); $font->align('center'); $font->size(37); }); }