123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457 |
- <?php
- namespace Grafika\Gd;
- use Grafika\Gd\Helper\GifHelper;
- use Grafika\ImageType;
- use Grafika\ImageInterface;
- /**
- * Image class for GD.
- * @package Grafika\Gd
- */
- final class Image implements ImageInterface {
- /**
- * @var resource GD resource ID.
- */
- private $gd;
- /**
- * @var string File path to image.
- */
- private $imageFile;
- /**
- * @var int Image width in pixels.
- */
- private $width;
- /**
- * @var int Image height in pixels.
- */
- private $height;
- /**
- * @var string Image type. See \Grafika\ImageType
- */
- private $type;
- /**
- * @var string Contains array of animated GIF data.
- */
- private $blocks;
- /**
- * @var bool True if animated GIF.
- */
- private $animated;
- /**
- * Image constructor.
- *
- * @param resource $gd Must use GD's imagecreate* family of functions to create a GD resource.
- * @param string $imageFile
- * @param int $width
- * @param int $height
- * @param string $type
- * @param string $blocks
- * @param bool $animated
- */
- public function __construct( $gd, $imageFile, $width, $height, $type, $blocks = '', $animated = false ) {
- $this->gd = $gd;
- $this->imageFile = $imageFile;
- $this->width = $width;
- $this->height = $height;
- $this->type = $type;
- $this->blocks = $blocks;
- $this->animated = $animated;
- }
- /**
- * Method called when 'clone' keyword is used.
- */
- public function __clone()
- {
- $original = $this->gd;
- $copy = imagecreatetruecolor($this->width, $this->height);
- imagecopy($copy, $original, 0, 0, 0, 0, $this->width, $this->height);
- $this->gd = $copy;
- }
- /**
- * Output a binary raw dump of an image in a specified format.
- *
- * @param string|ImageType $type Image format of the dump.
- *
- * @throws \Exception When unsupported type.
- */
- public function blob( $type = 'PNG' ) {
- $type = strtoupper($type);
- if ( ImageType::GIF == $type ) {
- imagegif( $this->gd );
- } else if ( ImageType::JPEG == $type ) {
- imagejpeg( $this->gd );
- } else if ( ImageType::PNG == $type ) {
- imagepng( $this->gd );
- } else if ( ImageType::WBMP == $type ) {
- imagewbmp( $this->gd );
- } else {
- throw new \Exception( sprintf( 'File type "%s" not supported.', $type ) );
- }
- }
- /**
- * Create Image from image file.
- *
- * @param string $imageFile Path to image.
- *
- * @return Image
- * @throws \Exception
- */
- public static function createFromFile( $imageFile ) {
- if ( ! file_exists( $imageFile ) ) {
- throw new \Exception( sprintf( 'Could not open "%s". File does not exist.', $imageFile ) );
- }
- $type = self::_guessType( $imageFile );
- if ( ImageType::GIF == $type ) {
- return self::_createGif( $imageFile );
- } else if ( ImageType::JPEG == $type ) {
- return self::_createJpeg( $imageFile );
- } else if ( ImageType::PNG == $type ) {
- return self::_createPng( $imageFile );
- } else if ( ImageType::WBMP == $type ) {
- return self::_createWbmp( $imageFile );
- } else {
- throw new \Exception( sprintf( 'Could not open "%s". File type not supported.', $imageFile ) );
- }
- }
- /**
- * Create an Image from a GD resource. The file type defaults to unknown.
- *
- * @param resource $gd GD resource.
- *
- * @return Image
- */
- public static function createFromCore( $gd ) {
- return new self( $gd, '', imagesx( $gd ), imagesy( $gd ), ImageType::UNKNOWN );
- }
- /**
- * Create a blank image.
- *
- * @param int $width Width in pixels.
- * @param int $height Height in pixels.
- *
- * @return Image
- */
- public static function createBlank($width = 1, $height = 1){
- return new self(imagecreatetruecolor($width, $height), '', $width, $height, ImageType::UNKNOWN);
- }
- /**
- * Set the blending mode for an image. Allows transparent overlays on top of an image.
- *
- * @param bool $flag True to enable blending mode.
- * @return self
- */
- public function alphaBlendingMode( $flag ){
- imagealphablending( $this->gd, $flag );
- return $this;
- }
- /**
- * Enable/Disable transparency
- *
- * @param bool $flag True to enable alpha mode.
- * @return self
- */
- public function fullAlphaMode( $flag ){
- if( true === $flag ){
- $this->alphaBlendingMode( false ); // Must be false for full alpha mode to work
- }
- imagesavealpha( $this->gd, $flag );
- return $this;
- }
- /**
- * Returns animated flag.
- *
- * @return bool True if animated GIF.
- */
- public function isAnimated() {
- return $this->animated;
- }
- /**
- * Get GD resource ID.
- *
- * @return resource
- */
- public function getCore() {
- return $this->gd;
- }
- /**
- * Get image file path.
- *
- * @return string File path to image.
- */
- public function getImageFile() {
- return $this->imageFile;
- }
- /**
- * Get image width in pixels.
- *
- * @return int
- */
- public function getWidth() {
- return $this->width;
- }
- /**
- * Get image height in pixels.
- *
- * @return int
- */
- public function getHeight() {
- return $this->height;
- }
- /**
- * Get image type.
- *
- * @return string
- */
- public function getType() {
- return $this->type;
- }
- /**
- * Get blocks.
- *
- * @return string.
- */
- public function getBlocks() {
- return $this->blocks;
- }
- /**
- * Get histogram from an entire image or its sub-region.
- *
- * @param array|null $slice Array of slice information. array( array( 0,0), array(100,50)) means x,y is 0,0 and width,height is 100,50
- *
- * @return array Returns array containing RGBA bins array('r'=>array(), 'g'=>array(), 'b'=>array(), 'a'=>array())
- */
- public function histogram($slice = null)
- {
- $gd = $this->getCore();
- if(null === $slice){
- $sliceX = 0;
- $sliceY = 0;
- $sliceW = $this->getWidth();
- $sliceH = $this->getHeight();
- } else {
- $sliceX = $slice[0][0];
- $sliceY = $slice[0][1];
- $sliceW = $slice[1][0];
- $sliceH = $slice[1][1];
- }
- $rBin = array();
- $gBin = array();
- $bBin = array();
- $aBin = array();
- for ($y = $sliceY; $y < $sliceY+$sliceH; $y++) {
- for ($x = $sliceX; $x < $sliceX+$sliceW; $x++) {
- $rgb = imagecolorat($gd, $x, $y);
- $a = ($rgb >> 24) & 0x7F; // 127 in hex. These are binary operations.
- $r = ($rgb >> 16) & 0xFF;
- $g = ($rgb >> 8) & 0xFF;
- $b = $rgb & 0xFF;
- if ( ! isset($rBin[$r])) {
- $rBin[$r] = 1;
- } else {
- $rBin[$r]++;
- }
- if ( ! isset($gBin[$g])) {
- $gBin[$g] = 1;
- } else {
- $gBin[$g]++;
- }
- if ( ! isset($bBin[$b])) {
- $bBin[$b] = 1;
- } else {
- $bBin[$b]++;
- }
- if ( ! isset($aBin[$a])) {
- $aBin[$a] = 1;
- } else {
- $aBin[$a]++;
- }
- }
- }
- return array(
- 'r' => $rBin,
- 'g' => $gBin,
- 'b' => $bBin,
- 'a' => $aBin
- );
- }
- /**
- * Load a GIF image.
- *
- * @param string $imageFile
- *
- * @return Image
- * @throws \Exception
- */
- private static function _createGif( $imageFile ){
- $gift = new GifHelper();
- $bytes = $gift->open($imageFile);
- $animated = $gift->isAnimated($bytes);
- $blocks = '';
- if($animated){
- $blocks = $gift->decode($bytes);
- }
- $gd = @imagecreatefromgif( $imageFile );
- if(!$gd){
- throw new \Exception( sprintf('Could not open "%s". Not a valid %s file.', $imageFile, ImageType::GIF) );
- }
- return new self(
- $gd,
- $imageFile,
- imagesx( $gd ),
- imagesy( $gd ),
- ImageType::GIF,
- $blocks,
- $animated
- );
- }
- /**
- * Load a JPEG image.
- *
- * @param string $imageFile File path to image.
- *
- * @return Image
- * @throws \Exception
- */
- private static function _createJpeg( $imageFile ){
- $gd = @imagecreatefromjpeg( $imageFile );
- if(!$gd){
- throw new \Exception( sprintf('Could not open "%s". Not a valid %s file.', $imageFile, ImageType::JPEG ) );
- }
- return new self( $gd, $imageFile, imagesx( $gd ), imagesy( $gd ), ImageType::JPEG );
- }
- /**
- * Load a PNG image.
- *
- * @param string $imageFile File path to image.
- *
- * @return Image
- * @throws \Exception
- */
- private static function _createPng( $imageFile ){
- $gd = @imagecreatefrompng( $imageFile );
- if(!$gd){
- throw new \Exception( sprintf('Could not open "%s". Not a valid %s file.', $imageFile, ImageType::PNG) );
- }
- $image = new self( $gd, $imageFile, imagesx( $gd ), imagesy( $gd ), ImageType::PNG );
- $image->fullAlphaMode( true );
- return $image;
- }
- /**
- * Load a WBMP image.
- *
- * @param string $imageFile
- *
- * @return Image
- * @throws \Exception
- */
- private static function _createWbmp( $imageFile ){
- $gd = @imagecreatefromwbmp( $imageFile );
- if(!$gd){
- throw new \Exception( sprintf('Could not open "%s". Not a valid %s file.', $imageFile, ImageType::WBMP) );
- }
- return new self( $gd, $imageFile, imagesx( $gd ), imagesy( $gd ), ImageType::WBMP );
- }
- /**
- * @param $imageFile
- *
- * @return string
- */
- private static function _guessType( $imageFile ){
- // Values from http://php.net/manual/en/image.constants.php starting with IMAGETYPE_GIF.
- // 0 - unknown,
- // 1 - GIF,
- // 2 - JPEG,
- // 3 - PNG
- // 15 - WBMP
- list($width, $height, $type) = getimagesize( $imageFile );
- unset($width, $height);
- if ( 1 == $type) {
- return ImageType::GIF;
- } else if ( 2 == $type) {
- return ImageType::JPEG;
- } else if ( 3 == $type) {
- return ImageType::PNG;
- } else if ( 15 == $type) {
- return ImageType::WBMP;
- }
- return ImageType::UNKNOWN;
- }
- }
|