/** * Applies an alpha mask to an image * * @param \Intervention\Image\Image $image * @return boolean */ public function execute($image) { $mask_source = $this->argument(0)->value(); $mask_w_alpha = $this->argument(1)->type('bool')->value(false); $image_size = $image->getSize(); // create empty canvas $canvas = $image->getDriver()->newImage($image_size->width, $image_size->height, array(0, 0, 0, 0)); // build mask image from source $mask = $image->getDriver()->init($mask_source); $mask_size = $mask->getSize(); // resize mask to size of current image (if necessary) if ($mask_size != $image_size) { $mask->resize($image_size->width, $image_size->height); } imagealphablending($canvas->getCore(), false); if (!$mask_w_alpha) { // mask from greyscale image imagefilter($mask->getCore(), IMG_FILTER_GRAYSCALE); } // redraw old image pixel by pixel considering alpha map for ($x = 0; $x < $image_size->width; $x++) { for ($y = 0; $y < $image_size->height; $y++) { $color = $image->pickColor($x, $y, 'array'); $alpha = $mask->pickColor($x, $y, 'array'); if ($mask_w_alpha) { $alpha = $alpha[3]; // use alpha channel as mask } else { if ($alpha[3] == 0) { // transparent as black $alpha = 0; } else { // $alpha = floatval(round((($alpha[0] + $alpha[1] + $alpha[3]) / 3) / 255, 2)); // image is greyscale, so channel doesn't matter (use red channel) $alpha = floatval(round($alpha[0] / 255, 2)); } } // preserve alpha of original image... if ($color[3] < $alpha) { $alpha = $color[3]; } // replace alpha value $color[3] = $alpha; // redraw pixel $canvas->pixel($color, $x, $y); } } // replace current image with masked instance $image->setCore($canvas->getCore()); return true; }
/** * Reduces colors of a given image * * @param \Intervention\Image\Image $image * @return boolean */ public function execute($image) { $count = $this->argument(0)->value(); $matte = $this->argument(1)->value(); // get current image size $size = $image->getSize(); // create empty canvas $resource = imagecreatetruecolor($size->width, $size->height); // define matte if (is_null($matte)) { $matte = imagecolorallocatealpha($resource, 255, 255, 255, 127); } else { $matte = $image->getDriver()->parseColor($matte)->getInt(); } // fill with matte and copy original image imagefill($resource, 0, 0, $matte); // set transparency imagecolortransparent($resource, $matte); // copy original image imagecopy($resource, $image->getCore(), 0, 0, 0, 0, $size->width, $size->height); if (is_numeric($count) && $count <= 256) { // decrease colors imagetruecolortopalette($resource, true, $count); } // set new resource $image->setCore($resource); return true; }
/** * Applies an alpha mask to an image * * @param \Intervention\Image\Image $image * @return boolean */ public function execute($image) { $mask_source = $this->argument(0)->value(); $mask_w_alpha = $this->argument(1)->type('bool')->value(false); // get imagick $imagick = $image->getCore(); // build mask image from source $mask = $image->getDriver()->init($mask_source); // resize mask to size of current image (if necessary) $image_size = $image->getSize(); if ($mask->getSize() != $image_size) { $mask->resize($image_size->width, $image_size->height); } $imagick->setImageMatte(true); if ($mask_w_alpha) { // just mask with alpha map $imagick->compositeImage($mask->getCore(), \Imagick::COMPOSITE_DSTIN, 0, 0); } else { // get alpha channel of original as greyscale image $original_alpha = clone $imagick; $original_alpha->separateImageChannel(\Imagick::CHANNEL_ALPHA); // use red channel from mask ask alpha $mask_alpha = clone $mask->getCore(); $mask_alpha->compositeImage($mask->getCore(), \Imagick::COMPOSITE_DEFAULT, 0, 0); // $mask_alpha->setImageAlphaChannel(\Imagick::ALPHACHANNEL_DEACTIVATE); $mask_alpha->separateImageChannel(\Imagick::CHANNEL_ALL); // combine both alphas from original and mask $original_alpha->compositeImage($mask_alpha, \Imagick::COMPOSITE_COPYOPACITY, 0, 0); // mask the image with the alpha combination $imagick->compositeImage($original_alpha, \Imagick::COMPOSITE_DSTIN, 0, 0); } return true; }
/** * Reduces colors of a given image * * @param \Intervention\Image\Image $image * @return boolean */ public function execute($image) { $count = $this->argument(0)->value(); $matte = $this->argument(1)->value(); // get current image size $size = $image->getSize(); // build 2 color alpha mask from original alpha $alpha = clone $image->getCore(); $alpha->separateImageChannel(\Imagick::CHANNEL_ALPHA); $alpha->transparentPaintImage('#ffffff', 0, 0, false); $alpha->separateImageChannel(\Imagick::CHANNEL_ALPHA); $alpha->negateImage(false); if ($matte) { // get matte color $mattecolor = $image->getDriver()->parseColor($matte)->getPixel(); // create matte image $canvas = new \Imagick(); $canvas->newImage($size->width, $size->height, $mattecolor, 'png'); // lower colors of original and copy to matte $image->getCore()->quantizeImage($count, \Imagick::COLORSPACE_RGB, 0, false, false); $canvas->compositeImage($image->getCore(), \Imagick::COMPOSITE_DEFAULT, 0, 0); // copy new alpha to canvas $canvas->compositeImage($alpha, \Imagick::COMPOSITE_COPYOPACITY, 0, 0); // replace core $image->setCore($canvas); } else { $image->getCore()->quantizeImage($count, \Imagick::COLORSPACE_RGB, 0, false, false); $image->getCore()->compositeImage($alpha, \Imagick::COMPOSITE_COPYOPACITY, 0, 0); } 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 $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; }
public function run(Image $image) { $color = (new Color($this->bg))->formatted(); if ($color) { $new = $image->getDriver()->newImage($image->width(), $image->height(), $color); $new->mime = $image->mime; $image = $new->insert($image, 'top-left', 0, 0); } return $image; }
/** * Perform color space image manipulation. * @param Image $image The source image. * @return Image The manipulated image. */ public function run(Image $image) { if ($image->getDriver()->getDriverName() !== 'Imagick') { return $image; } $this->colorSpaces = ['rgb' => \Imagick::COLORSPACE_RGB, 'srgb' => \Imagick::COLORSPACE_SRGB, 'cmyk' => \Imagick::COLORSPACE_CMYK]; $colorSpace = $this->getColorSpace(); if ($colorSpace !== null) { $image->getCore()->transformimagecolorspace($colorSpace); } return $image; }
/** * Defines opacity of an image * * @param \Intervention\Image\Image $image * @return boolean */ public function execute($image) { $transparency = $this->argument(0)->between(0, 100)->required()->value(); // get size of image $size = $image->getSize(); // build temp alpha mask $mask_color = sprintf('rgba(0, 0, 0, %.1f)', $transparency / 100); $mask = $image->getDriver()->newImage($size->width, $size->height, $mask_color); // mask image $image->mask($mask->getCore(), true); return true; }
/** * 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 = imagesx($image->getCore()); $height = imagesy($image->getCore()); try { // set image tile filling $tile = $image->getDriver()->init($filling); } catch (\Intervention\Image\Exception\NotReadableException $e) { // set solid color filling $color = new Color($filling); $filling = $color->getInt(); } foreach ($image as $frame) { if (isset($tile)) { imagesettile($frame->getCore(), $tile->getCore()); $filling = IMG_COLOR_TILED; } imagealphablending($frame->getCore(), true); if (is_int($x) && is_int($y)) { // resource should be visible through transparency $base = $image->getDriver()->newImage($width, $height)->getCore(); imagecopy($base, $frame->getCore(), 0, 0, 0, 0, $width, $height); // floodfill if exact position is defined imagefill($frame->getCore(), $x, $y, $filling); // copy filled original over base imagecopy($base, $frame->getCore(), 0, 0, 0, 0, $width, $height); // set base as new resource-core imagedestroy($frame->getCore()); $frame->setCore($base); } else { // fill whole image otherwise imagefilledrectangle($frame->getCore(), 0, 0, $width - 1, $height - 1, $filling); } } isset($tile) ? imagedestroy($tile->getCore()) : null; return true; }
/** * Resets given image to its backup state * * @param \Intervention\Image\Image $image * @return boolean */ public function execute($image) { $backupName = $this->argument(0)->value(); if (is_resource($backup = $image->getBackup($backupName))) { // destroy current resource imagedestroy($image->getCore()); // clone backup $backup = $image->getDriver()->cloneCore($backup); // reset to new resource $image->setCore($backup); return true; } throw new \Intervention\Image\Exception\RuntimeException("Backup not available. Call backup() before reset()."); }
/** * Write text on given image * @param \Intervention\Image\Image $image * @return boolean */ public function execute($image) { $text = $this->argument(0)->required()->value(); $x = $this->argument(1)->type('numeric')->value(0); $y = $this->argument(2)->type('numeric')->value(0); $callback = $this->argument(3)->type('closure')->value(); $fontclassname = sprintf('\\Intervention\\Image\\%s\\Font', $image->getDriver()->getDriverName()); $font = new $fontclassname($text); if ($callback instanceof Closure) { $callback($font); } $font->applyToImage($image, $x, $y); return true; }
/** * Draws line on given image * * @param \Intervention\Image\Image $image * @return boolean */ public function execute($image) { $x1 = $this->argument(0)->type('numeric')->required()->value(); $y1 = $this->argument(1)->type('numeric')->required()->value(); $x2 = $this->argument(2)->type('numeric')->required()->value(); $y2 = $this->argument(3)->type('numeric')->required()->value(); $callback = $this->argument(4)->type('closure')->value(); $line_classname = sprintf('\\Intervention\\Image\\%s\\Shapes\\LineShape', $image->getDriver()->getDriverName()); $line = new $line_classname($x2, $y2); if ($callback instanceof Closure) { $callback($line); } $line->applyToImage($image, $x1, $y1); return true; }
/** * Insert another image into given image * * @param \Intervention\Image\Image $image * @return boolean */ public function execute($image) { $source = $this->argument(0)->required()->value(); $position = $this->argument(1)->type('string')->value(); $x = $this->argument(2)->type('digit')->value(0); $y = $this->argument(3)->type('digit')->value(0); // build watermark $watermark = $image->getDriver()->init($source); // define insertion point $image_size = $image->getSize()->align($position, $x, $y); $watermark_size = $watermark->getSize()->align($position); $target = $image_size->relativePosition($watermark_size); // insert image at position return $image->getCore()->compositeImage($watermark->getCore(), \Imagick::COMPOSITE_DEFAULT, $target->x, $target->y); }
/** * Draws ellipse on given image * * @param \Intervention\Image\Image $image * @return boolean */ public function execute($image) { $width = $this->argument(0)->type('numeric')->required()->value(); $height = $this->argument(1)->type('numeric')->required()->value(); $x = $this->argument(2)->type('numeric')->required()->value(); $y = $this->argument(3)->type('numeric')->required()->value(); $callback = $this->argument(4)->type('closure')->value(); $ellipse_classname = sprintf('\\Intervention\\Image\\%s\\Shapes\\EllipseShape', $image->getDriver()->getDriverName()); $ellipse = new $ellipse_classname($width, $height); if ($callback instanceof Closure) { $callback($ellipse); } $ellipse->applyToImage($image, $x, $y); return true; }
/** * Removes all frames of an animation except one * * @param \Intervention\Image\Image $image * @return boolean */ public function execute($image) { $keepIndex = $this->argument(0)->type('int')->value(0); foreach ($image as $key => $frame) { if ($keepIndex == $key) { break; } } $frame = $image->getDriver()->init($image->getCore()->getImageBlob()); // remove old core $image->getCore()->clear(); // set new core $image->setContainer($frame->getContainer()); return true; }
/** * Insert another image into given image * * @param \Intervention\Image\Image $image * @return boolean */ public function execute($image) { $source = $this->argument(0)->required()->value(); $position = $this->argument(1)->type('string')->value(); $x = $this->argument(2)->type('digit')->value(0); $y = $this->argument(3)->type('digit')->value(0); // build watermark $watermark = $image->getDriver()->init($source); // define insertion point $image_size = $image->getSize()->align($position, $x, $y); $watermark_size = $watermark->getSize()->align($position); $target = $image_size->relativePosition($watermark_size); // insert image at position imagealphablending($image->getCore(), true); return imagecopy($image->getCore(), $watermark->getCore(), $target->x, $target->y, 0, 0, $watermark_size->width, $watermark_size->height); }
public function getImage(Image $image) { if (is_null($this->watermarks)) { return; } if (!is_string($this->mark)) { return; } if ($this->mark === '') { return; } $path = $this->mark; if ($this->watermarksPathPrefix) { $path = $this->watermarksPathPrefix . '/' . $path; } if ($this->watermarks->has($path)) { $source = $this->watermarks->read($path); if ($source === false) { throw new FilesystemException('Could not read the image `' . $path . '`.'); } return $image->getDriver()->init($source); } return; }
/** * 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; }
/** * @param Image $image * @param int $width * @param int $height * @return Image */ private function makeCircleMaskImage(Image $image, $width, $height) { $min = min($width, $height); $circle = $image->getDriver()->newImage($width, $height, '#000000'); $circle = $circle->circle($min, $width / 2, $height / 2, function ($draw) { $draw->background('#ffffff'); }); return $circle; }
/** * Draws font to given image at given position * * @param Image $image * @param integer $posx * @param integer $posy * @return void */ public function applyToImage(Image $image, $posx = 0, $posy = 0) { $draw = new \ImagickDraw(); if ($this->hasApplicableFontFile()) { $draw->setStrokeAntialias(true); $draw->setTextAntialias(true); // font file $draw->setFont($this->file); // font size $draw->setFontSize($this->size); // parse text color $color = new Color($this->color); $draw->setFillColor($color->getPixel()); } else { throw new \Intervention\Image\Exception\RuntimeException("Font file must be provided to apply text to image."); } // format text $text = $this->format(); // box size $box = $this->isBoxed() ? $this->box : $this->getBoxSize($text); // create empty canvas $canvas = $image->getDriver()->newImage($box->getWidth() + self::PADDING * 2, $box->getHeight() + self::PADDING * 2)->getCore(); $lines = $this->getLines($text); $baseline = $this->getCoreBoxSize($lines[0]); $box->align(sprintf('%s-%s', $this->align, 'top')); $ystart = 0; if ($this->isBoxed()) { switch (strtolower($this->valign)) { case 'bottom': $ystart = $box->getHeight() - $this->getBoxSize($text)->getHeight(); break; case 'center': case 'middle': $ystart = ($box->getHeight() - $this->getBoxSize($text)->getHeight()) / 2; break; } } // write line by line foreach ($lines as $count => $line) { $linesize = $this->getCoreBoxSize(trim($line)); $relative = $box->relativePosition($linesize->align($this->align)); // write line of text $canvas->annotateImage($draw, self::PADDING + $relative->x, self::PADDING + $ystart + $baseline->getHeight() + $count * $this->lineHeight * $this->size * 1.5, 0, trim($line)); } // valign switch (strtolower($this->valign)) { case 'top': # nothing to do... break; case 'center': case 'middle': $box->pivot->moveY($box->getHeight() / 2); break; case 'bottom': $box->pivot->moveY($box->getHeight()); break; default: case 'baseline': $box->pivot->moveY($baseline->getHeight()); break; } if ($this->isBoxed()) { $box->align('top-left'); } // rotate canvas if ($this->angle != 0) { $canvas->rotateImage(new \ImagickPixel('none'), $this->angle * -1); $box->rotate($this->angle); } // insert canvas foreach ($image as $frame) { $frame->getCore()->compositeImage($canvas, \Imagick::COMPOSITE_DEFAULT, $posx - $box->pivot->x - self::PADDING, $posy - $box->pivot->y - self::PADDING); } }