Qiang Xue
11 years ago
7 changed files with 322 additions and 371 deletions
@ -0,0 +1,273 @@
|
||||
<?php |
||||
/** |
||||
* @link http://www.yiiframework.com/ |
||||
* @copyright Copyright (c) 2008 Yii Software LLC |
||||
* @license http://www.yiiframework.com/license/ |
||||
*/ |
||||
|
||||
namespace yii\imagine; |
||||
|
||||
use Yii; |
||||
use Imagine\Exception\InvalidArgumentException; |
||||
use Imagine\Image\Box; |
||||
use Imagine\Image\Color; |
||||
use Imagine\Image\ImageInterface; |
||||
use Imagine\Image\ImagineInterface; |
||||
use Imagine\Image\ManipulatorInterface; |
||||
use Imagine\Image\Point; |
||||
use yii\base\InvalidConfigException; |
||||
use yii\base\InvalidParamException; |
||||
use yii\helpers\ArrayHelper; |
||||
|
||||
/** |
||||
* BaseImage provides concrete implementation for [[Image]]. |
||||
* |
||||
* Do not use BaseImage. Use [[Image]] instead. |
||||
* |
||||
* @author Antonio Ramirez <amigo.cobos@gmail.com> |
||||
* @author Qiang Xue <qiang.xue@gmail.com> |
||||
* @since 2.0 |
||||
*/ |
||||
class BaseImage |
||||
{ |
||||
/** |
||||
* GD2 driver definition for Imagine implementation using the GD library. |
||||
*/ |
||||
const DRIVER_GD2 = 'gd2'; |
||||
/** |
||||
* imagick driver definition. |
||||
*/ |
||||
const DRIVER_IMAGICK = 'imagick'; |
||||
/** |
||||
* gmagick driver definition. |
||||
*/ |
||||
const DRIVER_GMAGICK = 'gmagick'; |
||||
/** |
||||
* @var array|string the driver to use. This can be either a single driver name or an array of driver names. |
||||
* If the latter, the first available driver will be used. |
||||
*/ |
||||
public static $driver = [self::DRIVER_GMAGICK, self::DRIVER_IMAGICK, self::DRIVER_GD2]; |
||||
|
||||
/** |
||||
* @var ImagineInterface instance. |
||||
*/ |
||||
private static $_imagine; |
||||
|
||||
/** |
||||
* Returns the `Imagine` object that supports various image manipulations. |
||||
* @return ImagineInterface the `Imagine` object |
||||
*/ |
||||
public static function getImagine() |
||||
{ |
||||
if (static::$_imagine === null) { |
||||
static::$_imagine = static::createImagine(); |
||||
} |
||||
return static::$_imagine; |
||||
} |
||||
|
||||
/** |
||||
* @param Imagine\Image\ImagineInterface $imagine the `Imagine` object. |
||||
*/ |
||||
public static function setImagine($imagine) |
||||
{ |
||||
static::$_imagine = $imagine; |
||||
} |
||||
|
||||
/** |
||||
* Creates an `Imagine` object based on the specified [[driver]]. |
||||
* @return ImagineInterface the new `Imagine` object |
||||
* @throws InvalidConfigException if [[driver]] is unknown or the system doesn't support any [[driver]]. |
||||
*/ |
||||
protected static function createImagine() |
||||
{ |
||||
foreach ((array)static::$driver as $driver) { |
||||
switch ($driver) { |
||||
case self::DRIVER_GMAGICK: |
||||
if (class_exists('Gmagick', false)) { |
||||
return new \Imagine\Gmagick\Imagine(); |
||||
} |
||||
break; |
||||
case self::DRIVER_IMAGICK: |
||||
if (!class_exists('Imagick', false)) { |
||||
return new \Imagine\Imagick\Imagine(); |
||||
} |
||||
break; |
||||
case self::DRIVER_GD2: |
||||
if (!function_exists('gd_info')) { |
||||
return new \Imagine\Gd\Imagine(); |
||||
} |
||||
break; |
||||
default: |
||||
throw new InvalidConfigException("Unknown driver: $driver"); |
||||
} |
||||
} |
||||
throw new InvalidConfigException("Your system does not support any of these drivers: " . implode(',', (array)static::$driver)); |
||||
} |
||||
|
||||
/** |
||||
* Crops an image. |
||||
* |
||||
* For example, |
||||
* |
||||
* ~~~ |
||||
* $obj->crop('path\to\image.jpg', 200, 200, [5, 5]); |
||||
* |
||||
* $point = new \Imagine\Image\Point(5, 5); |
||||
* $obj->crop('path\to\image.jpg', 200, 200, $point); |
||||
* ~~~ |
||||
* |
||||
* @param string $filename the image file path or path alias. |
||||
* @param integer $width the crop width |
||||
* @param integer $height the crop height |
||||
* @param array|Point $start the starting point. This can be either an array of `x` and `y` coordinates, or |
||||
* a `Point` object. |
||||
* @return ImageInterface |
||||
* @throws InvalidParamException if the `$start` parameter is invalid |
||||
*/ |
||||
public static function crop($filename, $width, $height, $start = [0, 0]) |
||||
{ |
||||
if (is_array($start)) { |
||||
if (isset($start[0], $start[1])) { |
||||
$start = new Point($start[0], $start[1]); |
||||
} else { |
||||
throw new InvalidParamException('$start must be an array of two elements.'); |
||||
} |
||||
} |
||||
|
||||
if ($start instanceof Point) { |
||||
return static::getImagine() |
||||
->open(Yii::getAlias($filename)) |
||||
->copy() |
||||
->crop($start, new Box($width, $height)); |
||||
} else { |
||||
throw new InvalidParamException('$start must be either an array or an "Imagine\\Image\\Point" object.'); |
||||
} |
||||
} |
||||
|
||||
/** |
||||
* Creates a thumbnail image. The function differs from [[\Imagine\Image\ImageInterface::thumbnail()]] function that |
||||
* it keeps the aspect ratio of the image. |
||||
* @param string $filename the image file path or path alias. |
||||
* @param integer $width the width in pixels to create the thumbnail |
||||
* @param integer $height the height in pixels to create the thumbnail |
||||
* @param string $mode |
||||
* @return ImageInterface |
||||
*/ |
||||
public static function thumbnail($filename, $width, $height, $mode = ManipulatorInterface::THUMBNAIL_OUTBOUND) |
||||
{ |
||||
$box = new Box($width, $height); |
||||
$img = static::getImagine()->open(Yii::getAlias($filename)); |
||||
|
||||
if (($img->getSize()->getWidth() <= $box->getWidth() && $img->getSize()->getHeight() <= $box->getHeight()) || (!$box->getWidth() && !$box->getHeight())) { |
||||
return $img->copy(); |
||||
} |
||||
|
||||
$img = $img->thumbnail($box, $mode); |
||||
|
||||
// create empty image to preserve aspect ratio of thumbnail |
||||
$thumb = static::getImagine()->create($box); |
||||
|
||||
// calculate points |
||||
$size = $img->getSize(); |
||||
|
||||
$startX = 0; |
||||
$startY = 0; |
||||
if ($size->getWidth() < $width) { |
||||
$startX = ceil($width - $size->getWidth()) / 2; |
||||
} |
||||
if ($size->getHeight() < $height) { |
||||
$startY = ceil($height - $size->getHeight()) / 2; |
||||
} |
||||
|
||||
$thumb->paste($img, new Point($startX, $startY)); |
||||
|
||||
return $thumb; |
||||
} |
||||
|
||||
/** |
||||
* Adds a watermark to an existing image. |
||||
* @param string $filename the image file path or path alias. |
||||
* @param string $watermarkFilename the file path or path alias of the watermark image. |
||||
* @param array|Point $start the starting point. This can be either an array of `x` and `y` coordinates, or |
||||
* a `Point` object. |
||||
* @return ImageInterface |
||||
* @throws InvalidParamException if `$start` is invalid |
||||
*/ |
||||
public static function watermark($filename, $watermarkFilename, $start = [0, 0]) |
||||
{ |
||||
if (is_array($start)) { |
||||
if (isset($start[0], $start[1])) { |
||||
$start = new Point($start[0], $start[1]); |
||||
} else { |
||||
throw new InvalidParamException('$start must be an array of two elements.'); |
||||
} |
||||
} |
||||
|
||||
if ($start instanceof Point) { |
||||
$img = static::getImagine()->open(Yii::getAlias($filename)); |
||||
$watermark = static::getImagine()->open(Yii::getAlias($watermarkFilename)); |
||||
return $img->paste($watermark, $start); |
||||
} else { |
||||
throw new InvalidParamException('$start must be either an array or an "Imagine\\Image\\Point" object.'); |
||||
} |
||||
} |
||||
|
||||
/** |
||||
* Draws a text string on an existing image. |
||||
* @param string $filename the image file path or path alias. |
||||
* @param string $text the text to write to the image |
||||
* @param array $fontOptions the font options. The following options may be specified: |
||||
* |
||||
* - font: The path to the font file to use to style the text. This option is required. |
||||
* - color: The font color. Defaults to "fff". |
||||
* - size: The font size. Defaults to 12. |
||||
* - x: The X position to write the text. Defaults to 5. |
||||
* - y: The Y position to write the text. Defaults to 5. |
||||
* - angle: The angle to use to write the text. Defaults to 0. |
||||
* |
||||
* @return ImageInterface |
||||
* @throws InvalidParamException if `$fontOptions` is invalid |
||||
*/ |
||||
public static function text($filename, $text, array $fontOptions) |
||||
{ |
||||
$font = ArrayHelper::getValue($fontOptions, 'font'); |
||||
if ($font === null) { |
||||
throw new InvalidParamException('$fontOptions must contain a "font" key specifying which font file to use.'); |
||||
} |
||||
|
||||
$fontSize = ArrayHelper::getValue($fontOptions, 'size', 12); |
||||
$fontColor = ArrayHelper::getValue($fontOptions, 'color', 'fff'); |
||||
$fontPosX = ArrayHelper::getValue($fontOptions, 'x', 5); |
||||
$fontPosY = ArrayHelper::getValue($fontOptions, 'y', 5); |
||||
$fontAngle = ArrayHelper::getValue($fontOptions, 'angle', 0); |
||||
|
||||
$img = static::getImagine()->open(Yii::getAlias($filename)); |
||||
$font = static::getImagine()->font(Yii::getAlias($font), $fontSize, new Color($fontColor)); |
||||
|
||||
return $img->draw()->text($text, $font, new Point($fontPosX, $fontPosY), $fontAngle); |
||||
} |
||||
|
||||
/** |
||||
* Adds a frame around of the image. Please note that the image size will increase by `$margin` x 2. |
||||
* @param string $filename the full path to the image file |
||||
* @param integer $margin the frame size to add around the image |
||||
* @param string $color the frame color |
||||
* @param integer $alpha the alpha value of the frame. |
||||
* @return ImageInterface |
||||
*/ |
||||
public static function frame($filename, $margin = 5, $color = '000', $alpha = 100) |
||||
{ |
||||
$img = static::getImagine()->open(Yii::getAlias($filename)); |
||||
|
||||
$size = $img->getSize(); |
||||
|
||||
$pasteTo = new Point($margin, $margin); |
||||
$padColor = new Color($color, $alpha); |
||||
|
||||
$box = new Box($size->getWidth() + ceil($margin * 2), $size->getHeight() + ceil($margin * 2)); |
||||
|
||||
$image = static::getImagine()->create($box, $padColor); |
||||
|
||||
return $image->paste($img, $pasteTo); |
||||
} |
||||
} |
Loading…
Reference in new issue