Skip to content

Instantly share code, notes, and snippets.

@maximishchenko
Last active July 9, 2017 13:48
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save maximishchenko/43a84e23b3414c223b596ed612c69a16 to your computer and use it in GitHub Desktop.
Save maximishchenko/43a84e23b3414c223b596ed612c69a16 to your computer and use it in GitHub Desktop.
PHP Fill or Fit Image (based on gd library)
<?php
namespace common\widgets;
/**
* Crop fill or fit image with php-gd library
* @author Maxim Ishchenko <maxim.ishchenko@gmail.com>
* @version 1.0*
* @uses, @example
* @license GPL
* @license http://opensource.org/licenses/gpl-license.php GNU Public License
*
* $image = new ImageFill(
* array(
* 'source' => 'source.jpg', // required source image
* 'h' => 250, // optional, if missing uses ImageFill::DEFAULT_HEIGHT value
* 'w' => 250, // optional, if missing uses ImageFill::DEFAULT_WIDTH value
* 'mode' => 'fill', // optional, must be 'fit' or 'fill', default 'fill'
* 'saveFile' => false, // optional, is need to save file, default - true, must be boolean, file be saved into ImageFill::DESTINATION_PATH
* )
* );
*
* @property string $source
* @property integer $h
* @property integer $w
* @property string $mode
* @property bool $saveFile
*/
class ImageFill
{
/**
* @constant MIN_HEIGHT minimal image height
* @constant MIN_WIDTH minimal image width
* @constant MAX_HEIGHT maximum available image height
* @constant MAX_WIDTH maximum available image width
* @constant DEFAULT_WIDTH standart image width
* @constant DEFAULT_HEIGHT standart image height
* @constant DEFAULT_MODE standart mode (if not set in $args array)
* @constant DESTINATION_PATH path to save output images (if $saveFile argument is true)
*/
const MIN_HEIGHT = 1;
const MIN_WIDTH = 1;
const MAX_HEIGHT = 1000;
const MAX_WIDTH = 1000;
const DEFAULT_HEIGHT = 100;
const DEFAULT_WIDTH = 100;
const DEFAULT_MODE = 'fill';
const DESTINATION_PATH = 'images/output.jpg';
/**
* @access private
* @property integer $h
* @property integer $w
* @property bool $saveFile
* @property string $mode
* @property string $source
* @property array $availableModes
*/
private $h;
private $w;
private $saveFile;
private $mode;
private $source;
private $availableModes = array('fit', 'fill');
function __construct($args = array())
{
/**
* source required
* @property string $source
* @access private
* @return Exception if not set or image resourse if variable is set
*/
if(!isset($args['source'])) {
throw new Exception("FillImage. One or more required parameters are missing!", 1);
} else {
/**
* @link http://php.net/manual/ru/function.imagecreatefromjpeg.php
*/
$this->source = imagecreatefromjpeg($args['source']);
}
/**
* Set default source value to DEFAULT_MODE constant if $mode is not set
* Check if mode is in range (fit, fill)
* @constant DEFAULT_MODE
* @property string $mode
* @access private
* @return Exception if not in range from $availableModes array, else return pre-defined value
*/
if(isset($args['mode']) && !in_array($args['mode'], $this->availableModes)) {
throw new Exception("FillImage. Incorrect mode!", 1);
} else {
$this->mode = (isset($args['mode']) && $args['mode'] == 'fit') ? 'fit' : self::DEFAULT_MODE;
}
/**
* Check if isset $saveFile, is $saveFile is boolean and set it to true if not set
* @property bool $saveFile
* @access private
* @return true | false
*/
if($args['saveFile'] !== null && !is_bool($args['saveFile'])) {
throw new Exception("Incorrect saveFile value", 1);
} elseif($args['saveFile'] !== null && is_bool($args['saveFile'])) {
$this->saveFile = $args['saveFile'];
} else {
$this->saveFile = true;
}
/**
* Check if isset $h value. If not set it to DEFAULT_HEIGHT
* Alse check if $h value in range (MIN_HEIGHT, MAX_HEIGHT), if not - set to DEFAULT_HEIGHT
* @constant MIN_HEIGHT
* @constant MIN_WIDTH
* @constant MAX_HEIGHT
* @constant MAX_WIDTH
* @property integer $h
* @access private
* @return integer $h value from $args array if it set or set $h to DEFAULT_HEIGHT value
*/
if(isset($args['h'])) {
/**
* @link http://php.net/manual/ru/function.intval.php
*/
$this->h = intval($args['h']);
$this->h = ($this->h <= self::MIN_HEIGHT || $this->h >= self::MAX_HEIGHT) ? self::DEFAULT_HEIGHT : $this->h;
} else {
$this->h = self::DEFAULT_HEIGHT;
}
/**
* Check if isset $w value. If not set it to DEFAULT_HEIGHT
* Alse check if $w value in range (MIN_HEIGHT, MAX_HEIGHT), if not - set to DEFAULT_HEIGHT
* @constant MIN_WIDTH
* @constant MAX_WIDTH
* @constant DEFAULT_WIDTH
* @property integer $w
* @access private
* @return integer $w value from $args array if it set or set $w to DEFAULT_HEIGHT value
*/
if(isset($args['w'])) {
/**
* @link http://php.net/manual/ru/function.intval.php
*/
$this->w = intval($args['w']);
$this->w = ($this->w <= self::MIN_WIDTH || $this->w >= self::MAX_WIDTH) ? self::DEFAULT_WIDTH : $this->w;
} else {
$this->w = self::DEFAULT_WIDTH;
}
/**
* Run result function to get croped-image
* @see getDestinationImage()
*/
$this->getDestinationImage();
}
/**
* @access private
* @constant DEFAULT_MODE
* @property string $source
* @param string $dst_image
* @var integer $new_width
* @var integer $new_height
* @var integer $new_x
* @var integer $new_y
* @var integer $next
* @var integer $dst_width
* @var integer $src_height
* @var integer $src_width
* @var integer $dst_height
* @var string $dst_image
*/
private function scaleImage($dst_image)
{
/**
* Get source image width
* @link http://php.net/manual/ru/function.imagesx.php
*/
$src_width = imagesx($this->source);
/**
* Get source image height
* @link http://php.net/manual/ru/function.imagesy.php
*/
$src_height = imagesy($this->source);
/**
* Get destination image width
* @link http://php.net/manual/ru/function.imagesx.php
*/
$dst_width = imagesx($dst_image);
/**
* Get destination image height
*/
$dst_height = imagesy($dst_image);
/**
* Try to match destination image by width
* @link http://php.net/manual/ru/function.imagesy.php
*/
$new_width = $dst_width;
$new_height = round($new_width*($src_height/$src_width));
$new_x = 0;
/**
* @link http://php.net/manual/ru/function.round.php
*/
$new_y = round(($dst_height-$new_height)/2);
$next = $this->mode == self::DEFAULT_MODE ? $new_height < $dst_height : $new_height > $dst_height;
/**
* If match by width failed and destination image does not fit, try by height
*/
if ($next) {
$new_height = $dst_height;
/**
* @link http://php.net/manual/ru/function.round.php
*/
$new_width = round($new_height*($src_width/$src_height));
$new_x = round(($dst_width - $new_width)/2);
$new_y = 0;
}
/**
* Copy image on right place
* @link http://php.net/manual/ru/function.imagecopyresampled.php
*/
imagecopyresampled($dst_image, $this->source , $new_x, $new_y, 0, 0, $new_width, $new_height, $src_width, $src_height);
}
/**
* Return destination image to browser or save it to file
* @access private
* @property integer $w
* @property integer $h
* @property bool $saveFile
* @param string $dst
*/
private function getDestinationImage()
{
/**
* @link http://php.net/manual/ru/function.imagecreatetruecolor.php
*/
$dst = imagecreatetruecolor($this->w, $this->h);
/**
* @link http://php.net/manual/ru/function.imagefill.php
*/
imagefill($dst, 0, 0, imagecolorallocate($dst, 255, 255, 255));
/**
* @see $scaleImage
*/
$this->scaleImage($dst);
/**
* Output to the browser
* @link http://php.net/manual/ru/function.imagejpeg.php
*/
imagejpeg($dst, ($this->saveFile) ? self::DESTINATION_PATH : null);
}
}
// Header('Content-Type: image/jpeg');
/**
* @see ImageFill()
*/
// $image = new ImageFill(
// array(
// 'h' => 250,
// 'w' => 250,
// 'source' => 'source.jpg',
// 'mode' => 'fill',
// 'saveFile' => false,
// )
// );
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment