File manager - Edit - /home/infoilmg/public_html/wp-content/plugins/fs-poster/App/Libraries/PHPImage/PHPImage.php
Back
<?php namespace FSPoster\App\Libraries\PHPImage; use stdClass; use Exception; /** * Wrapper for PHP's GD Library for easy image manipulation to resize, crop * and draw images on top of each other preserving transparency, writing text * with stroke and transparency and drawing shapes. * * @version 0.6.1 * @author Blake Kus <blakekus@gmail.com> * @license MIT License (http://www.opensource.org/licenses/mit-license.php) * @copyright 2015 Blake Kus * * CHANGELOG: * version 0.6.1 2017-12-04 * FIXED: Stroke losing colour on multiline text (Thanks @choice2rejoice) * * version 0.6 2017-10-26 * UPDATE: Support text alignment for multiline text * ADD: Configurable line height * ADD: OTF font support (Thanks @thorerik) * * version 0.5 2015-01-02 * ADD: textBox auto scale font to width and height requested by @rufinus https://github.com/kus/php-image/issues/3 * * version 0.4 2014-02-27 * ADD: Image support for image cloning (Thanks @chainat) * ADD: Support to use GD commands to manipulate image and then continue using library * UPDATE: Private to Protected so library is extendable * ADD: Rotate * * version 0.3 2014-02-12 * ADD: Examples * ADD: Initialise image on class instantiation * ADD: Image resize with optional upscaling * ADD: Image batch resize * ADD: Image crop * ADD: Option to save as gif/jpg/png * ADD: Snapshot images * FIX: Error in `textBox` reported by elbaku https://github.com/kus/php-image/issues/1 * * version 0.2 2013-05-23 * Add support for remote images * Add error handling when reading/writing files * Add ability to draw text box and auto fit text and align text * * version 0.1 2013-04-15 * Initial release */ class PHPImage { /** * Canvas resource * * @var resource */ protected $img; /** * Canvas resource * * @var resource */ protected $img_copy; /** * PNG Compression level: from 0 (no compression) to 9. * JPEG Compression level: from 0 to 100 (no compression). * * @var integer */ protected $quality = 90; /** * Global font file * * @var String */ protected $fontFile; /** * Global font size * * @var integer */ protected $fontSize = 12; /** * Global line height * * @var float */ protected $lineHeight = 1.25; /** * Global text vertical alignment * * @var String */ protected $alignVertical = 'top'; /** * Global text horizontal alignment * * @var String */ protected $alignHorizontal = 'left'; /** * Global font colour * * @var array */ protected $textColor = [ 255, 255, 255 ]; /** * Global text opacity * * @var float */ protected $textOpacity = 1; /** * Global text angle * * @var integer */ protected $textAngle = 0; /** * Global stroke width * * @var integer */ protected $strokeWidth = 0; /** * Global stroke colour * * @var array */ protected $strokeColor = [ 0, 0, 0 ]; /** * Canvas width * * @var integer */ protected $width; /** * Canvas height * * @var integer */ protected $height; /** * Image type * * @var integer */ protected $type; /** * Default folder mode to be used if folder structure needs to be created * * @var String */ protected $folderMode = 0755; /** * Initialise the image with a file path, or dimensions, or pass no dimensions and * use setDimensionsFromImage to set dimensions from another image. * * @param string|integer $mixed (optional) file or width * @param integer $height (optional) * * @return $this */ public function __construct ( $mixed = NULL, $height = NULL ) { //Check if GD extension is loaded if ( ! extension_loaded( 'gd' ) && ! extension_loaded( 'gd2' ) ) { $this->handleError( 'GD is not loaded' ); return FALSE; } if ( $mixed !== NULL && $height !== NULL ) { $this->initialiseCanvas( $mixed, $height ); } else if ( $mixed !== NULL && is_string( $mixed ) ) { $image = $this->setDimensionsFromImage( $mixed ); $image->draw( $mixed ); return $image; } } /** * Intialise the canvas * * @param integer $width * @param integer $height * * @return $this */ public function initialiseCanvas ( $width, $height, $resource = 'img', $color = [ 0, 0, 0, 127 ] ) { $this->width = $width; $this->height = $height; unset( $this->$resource ); $this->$resource = imagecreatetruecolor( $this->width, $this->height ); // Set the flag to save full alpha channel information imagesavealpha( $this->$resource, TRUE ); // Turn off transparency blending (temporarily) imagealphablending( $this->$resource, FALSE ); // Completely fill the background with transparent color imagefilledrectangle( $this->$resource, 0, 0, $this->width, $this->height, imagecolorallocatealpha( $this->$resource, $color[ 0 ], $color[ 1 ], $color[ 2 ], $color[ 3 ] ) ); // Restore transparency blending imagealphablending( $this->$resource, TRUE ); return $this; } /** * After we update the image run this function */ protected function afterUpdate () { $this->shadowCopy(); } /** * Store a copy of the image to be used for clone */ protected function shadowCopy () { $this->initialiseCanvas( $this->width, $this->height, 'img_copy' ); imagecopy( $this->img_copy, $this->img, 0, 0, 0, 0, $this->width, $this->height ); } /** * Enable cloning of images in their current state * * $one = clone $image; */ public function __clone () { $this->initialiseCanvas( $this->width, $this->height ); imagecopy( $this->img, $this->img_copy, 0, 0, 0, 0, $this->width, $this->height ); } /** * Get image height * * @return int */ public function getHeight () { return $this->height; } /** * Get image width * * @return int */ public function getWidth () { return $this->width; } /** * Get image resource (used when using a raw gd command) * * @return resource */ public function getResource () { return $this->img; } /** * Set image resource (after using a raw gd command) * * @param $resource * * @return $this */ public function setResource ( $resource ) { $this->img = $resource; $this->width = imagesx( $resource ); $this->height = imagesy( $resource ); return $this; } /** * Set image dimensions from an image source * * @param String $file * * @return $this */ public function setDimensionsFromImage ( $file ) { if ( $info = $this->getImageInfo( $file, FALSE ) ) { $this->initialiseCanvas( $info->width, $info->height ); return $this; } else { $this->handleError( $file . ' is not readable!' ); } } /** * Check if an image (remote or local) is a valid image and return type, width, height and image resource * * @param string $file * @param boolean $returnResource * * @return stdClass */ protected function getImageInfo ( $file, $returnResource = TRUE ) { if ( $file instanceof PHPIMage ) { $img = $file->img; $type = $file->type; $width = $file->width; $height = $file->height; } else if ( preg_match( '#^https?://#i', $file ) ) { $headers = get_headers( $file, 1 ); if ( is_array( $headers[ 'Content-Type' ] ) ) { // Some servers return an array of content types, Facebook does this $contenttype = $headers[ 'Content-Type' ][ 0 ]; } else { $contenttype = $headers[ 'Content-Type' ]; } if ( preg_match( '#^image/(jpe?g|png|gif)$#i', $contenttype ) ) { switch ( TRUE ) { case stripos( $contenttype, 'jpeg' ) !== FALSE: case stripos( $contenttype, 'jpg' ) !== FALSE: $img = imagecreatefromjpeg( $file ); $type = IMAGETYPE_JPEG; break; case stripos( $contenttype, 'png' ) !== FALSE: $img = imagecreatefrompng( $file ); $type = IMAGETYPE_PNG; break; case stripos( $contenttype, 'gif' ) !== FALSE: $img = imagecreatefromgif( $file ); $type = IMAGETYPE_GIF; break; default: return FALSE; } $width = imagesx( $img ); $height = imagesy( $img ); if ( ! $returnResource ) { imagedestroy( $img ); } } else { return FALSE; } } else if ( is_readable( $file ) ) { list( $width, $height, $type ) = getimagesize( $file ); switch ( $type ) { case IMAGETYPE_GIF: if ( $returnResource ) { $img = imagecreatefromgif( $file ); } break; case IMAGETYPE_JPEG: if ( $returnResource ) { $img = imagecreatefromjpeg( $file ); } break; case IMAGETYPE_PNG: if ( $returnResource ) { $img = imagecreatefrompng( $file ); } break; default: return FALSE; } } else { return FALSE; } $info = new stdClass(); $info->type = $type; if ( $this->type === NULL ) { // Assuming the first image you use is the output image type you want $this->type = $type; } $info->width = $width; $info->height = $height; if ( $returnResource ) { $info->resource = $img; } return $info; } /** * Handle errors * * @param String $error * * @throws Exception */ protected function handleError ( $error ) { throw new Exception( $error ); } /** * Rotate image * * @param $angle * @param int $bgd_color * @param int $ignore_transparent * * @return $this */ public function rotate ( $angle, $bgd_color = 0, $ignore_transparent = 0 ) { $this->img = imagerotate( $this->img, $angle, 0 ); $this->afterUpdate(); return $this; } /** * Crop an image * * @param integer $x * @param integer $y * @param integer $width * @param integer $height * * @return $this */ public function crop ( $x, $y, $width, $height ) { $tmp = $this->img; $this->initialiseCanvas( $width, $height ); imagecopyresampled( $this->img, $tmp, 0, 0, $x, $y, $width, $height, $width, $height ); imagedestroy( $tmp ); $this->afterUpdate(); return $this; } /** * Batch resize and save * * Usage: $image->batchResize('/path/to/img/test_%dx%d.jpg', array(array(100, 100, 'C', true),array(50, 50))); * * Will result in two images being saved (test_100x100.jpg and test_50x50.jpg) with 100x100 being cropped to the center. * * @param String $path * @param array $dimensions Array of `resize` arguments to run and save ie: array(100, 100, true, true) * * @return $this */ public function batchResize ( $path, $dimensions = [] ) { if ( is_array( $dimensions ) && count( $dimensions ) > 0 ) { $width = $this->width; $height = $this->height; $copy = imagecreatetruecolor( $width, $height ); imagecopy( $copy, $this->img, 0, 0, 0, 0, $width, $height ); foreach ( $dimensions as $args ) { $this->initialiseCanvas( $width, $height ); imagecopy( $this->img, $copy, 0, 0, 0, 0, $width, $height ); call_user_func_array( [ $this, 'resize' ], $args ); $this->save( sprintf( $path, $args[ 0 ], $args[ 1 ] ) ); } $this->initialiseCanvas( $width, $height ); imagecopy( $this->img, $copy, 0, 0, 0, 0, $width, $height ); imagedestroy( $copy ); } return $this; } /** * Resize image to desired dimensions. * * Optionally crop the image using the quadrant. * * This function attempts to get the image to as close to the provided dimensions as possible, and then crops the * remaining overflow using the quadrant to get the image to be the size specified. * * The quadrants available are Top, Bottom, Center (default if crop = true), Left, and Right: * * +---+---+---+ * | | T | | * +---+---+---+ * | L | C | R | * +---+---+---+ * | | B | | * +---+---+---+ * * @param integer $targetWidth * @param integer $targetHeight * @param boolean|String $crop T, B, C, L, R * @param boolean $upscale * * @return $this */ public function resize ( $targetWidth, $targetHeight, $crop = FALSE, $upscale = FALSE ) { $width = $this->width; $height = $this->height; $canvasWidth = $targetWidth; $canvasHeight = $targetHeight; $r = $width / $height; $x = 0; $y = 0; if ( $crop !== FALSE ) { if ( $crop === TRUE ) { $crop = 'C'; } if ( $targetWidth / $targetHeight > $r ) { // crop top/bottom $newheight = intval( $targetWidth / $r ); $newwidth = $targetWidth; switch ( $crop ) { case 'T': $y = 0; break; case 'B': $y = intval( ( $newheight - $targetHeight ) * ( $height / $newheight ) ); break; case 'C': default: $y = intval( ( ( $newheight - $targetHeight ) / 2 ) * ( $height / $newheight ) ); break; } } else { // crop sides $newwidth = intval( $targetHeight * $r ); $newheight = $targetHeight; switch ( $crop ) { case 'L': $x = 0; break; case 'R': $x = intval( ( $newwidth - $targetWidth ) * ( $width / $newwidth ) ); break; case 'C': default: $x = intval( ( ( $newwidth - $targetWidth ) / 2 ) * ( $width / $newwidth ) ); break; } } if ( $upscale === FALSE ) { if ( $newwidth > $width ) { $x = 0; $newwidth = $width; $canvasWidth = $newwidth; } if ( $newheight > $height ) { $y = 0; $newheight = $height; $canvasHeight = $newheight; } } } else { if ( $targetWidth / $targetHeight > $r ) { $newwidth = intval( $targetHeight * $r ); $newheight = $targetHeight; } else { $newheight = intval( $targetWidth / $r ); $newwidth = $targetWidth; } if ( $upscale === FALSE ) { if ( $newwidth > $width ) { $newwidth = $width; } if ( $newheight > $height ) { $newheight = $height; } } $canvasWidth = $newwidth; $canvasHeight = $newheight; } $tmp = $this->img; $this->initialiseCanvas( $canvasWidth, $canvasHeight ); imagecopyresampled( $this->img, $tmp, 0, 0, $x, $y, $newwidth, $newheight, $width, $height ); imagedestroy( $tmp ); $this->afterUpdate(); return $this; } /** * Shows the resulting image and cleans up. */ public function show () { $this->checkQuality(); switch ( $this->type ) { case IMAGETYPE_GIF: header( 'Content-type: image/gif' ); imagegif( $this->img, NULL ); break; case IMAGETYPE_PNG: header( 'Content-type: image/png' ); imagepng( $this->img, NULL, $this->quality ); break; default: header( 'Content-type: image/jpeg' ); imagejpeg( $this->img, NULL, $this->quality ); break; } $this->cleanup(); } /** * Cleanup */ public function cleanup () { imagedestroy( $this->img ); } /** * Save the image * * @param String $path * @param boolean $show * @param boolean $destroy * * @return $this */ public function save ( $path, $show = FALSE, $destroy = TRUE ) { if ( ! is_writable( dirname( $path ) ) ) { if ( ! mkdir( dirname( $path ), $this->folderMode, TRUE ) ) { $this->handleError( dirname( $path ) . ' is not writable and failed to create directory structure!' ); } } if ( is_writable( dirname( $path ) ) ) { $this->checkQuality(); switch ( $this->type ) { case IMAGETYPE_GIF: imagegif( $this->img, $path ); break; case IMAGETYPE_PNG: imagepng( $this->img, $path, $this->quality ); break; default: imagejpeg( $this->img, $path, $this->quality ); break; } } else { $this->handleError( dirname( $path ) . ' is not writable!' ); } if ( $show ) { $this->show(); return; } if ( $destroy ) { $this->cleanup(); } else { return $this; } } /** * Save the image and return object to continue operations * * @param string $path * * @return $this */ public function snapshot ( $path ) { return $this->save( $path, FALSE, FALSE ); } /** * Save the image and show it * * @param string $path */ public function showAndSave ( $path ) { $this->save( $path, TRUE ); } /** * Draw a line * * @param integer $x1 * @param integer $y1 * @param integer $x2 * @param integer $y2 * @param array $colour * @param float $opacity * @param boolean $dashed * * @return $this */ public function line ( $x1 = 0, $y1 = 0, $x2 = 100, $y2 = 100, $colour = [ 0, 0, 0 ], $opacity = 1.0, $dashed = FALSE ) { if ( $dashed === TRUE ) { imagedashedline( $this->img, $x1, $y1, $x2, $y2, imagecolorallocatealpha( $this->img, $colour[ 0 ], $colour[ 1 ], $colour[ 2 ], ( 1 - $opacity ) * 127 ) ); } else { imageline( $this->img, $x1, $y1, $x2, $y2, imagecolorallocatealpha( $this->img, $colour[ 0 ], $colour[ 1 ], $colour[ 2 ], ( 1 - $opacity ) * 127 ) ); } $this->afterUpdate(); return $this; } /** * Draw a rectangle * * @param integer $x * @param integer $y * @param integer $width * @param integer $height * @param array $colour * @param float $opacity * @param boolean $outline * * @return $this * @see http://www.php.net/manual/en/function.imagefilledrectangle.php */ public function rectangle ( $x = 0, $y = 0, $width = 100, $height = 50, $colour = [ 0, 0, 0 ], $opacity = 1.0, $outline = FALSE ) { if ( $outline === TRUE ) { imagerectangle( $this->img, $x, $y, $x + $width, $y + $height, imagecolorallocatealpha( $this->img, $colour[ 0 ], $colour[ 1 ], $colour[ 2 ], ( 1 - $opacity ) * 127 ) ); } else { imagefilledrectangle( $this->img, $x, $y, $x + $width, $y + $height, imagecolorallocatealpha( $this->img, $colour[ 0 ], $colour[ 1 ], $colour[ 2 ], ( 1 - $opacity ) * 127 ) ); } $this->afterUpdate(); return $this; } /** * Draw a square * * @param integer $x * @param integer $y * @param integer $width * @param array $colour * @param float $opacity * @param boolean $outline * * @return $this * @see http://www.php.net/manual/en/function.imagefilledrectangle.php */ public function square ( $x = 0, $y = 0, $width = 100, $colour = [ 0, 0, 0 ], $opacity = 1.0, $outline = FALSE ) { return $this->rectangle( $x, $y, $width, $width, $colour, $opacity, $outline ); } /** * Draw an ellipse * * @param integer $x * @param integer $y * @param integer $width * @param integer $height * @param array $colour * @param float $opacity * @param boolean $outline * * @return $this * @see http://www.php.net/manual/en/function.imagefilledellipse.php */ public function ellipse ( $x = 0, $y = 0, $width = 100, $height = 50, $colour = [ 0, 0, 0 ], $opacity = 1.0, $outline = FALSE ) { if ( $outline === TRUE ) { imageellipse( $this->img, $x, $y, $width, $height, imagecolorallocatealpha( $this->img, $colour[ 0 ], $colour[ 1 ], $colour[ 2 ], ( 1 - $opacity ) * 127 ) ); } else { imagefilledellipse( $this->img, $x, $y, $width, $height, imagecolorallocatealpha( $this->img, $colour[ 0 ], $colour[ 1 ], $colour[ 2 ], ( 1 - $opacity ) * 127 ) ); } $this->afterUpdate(); return $this; } /** * Draw a circle * * @param integer $x * @param integer $y * @param integer $width * @param array $colour * @param float $opacity * @param boolean $outline * * @return $this * @see http://www.php.net/manual/en/function.imagefilledellipse.php */ public function circle ( $x = 0, $y = 0, $width = 100, $colour = [ 0, 0, 0 ], $opacity = 1.0, $outline = FALSE ) { return $this->ellipse( $x, $y, $width, $width, $colour, $opacity, $outline ); } /** * Draw a polygon * * @param array $points * @param array $colour * @param float $opacity * @param boolean $outline * * @return $this * @see http://www.php.net/manual/en/function.imagefilledpolygon.php */ public function polygon ( $points = [], $colour = [ 0, 0, 0 ], $opacity = 1.0, $outline = FALSE ) { if ( count( $points ) > 0 ) { if ( $outline === TRUE ) { imagepolygon( $this->img, $points, count( $points ) / 2, imagecolorallocatealpha( $this->img, $colour[ 0 ], $colour[ 1 ], $colour[ 2 ], ( 1 - $opacity ) * 127 ) ); } else { imagefilledpolygon( $this->img, $points, count( $points ) / 2, imagecolorallocatealpha( $this->img, $colour[ 0 ], $colour[ 1 ], $colour[ 2 ], ( 1 - $opacity ) * 127 ) ); } $this->afterUpdate(); } return $this; } /** * Draw an arc * * @param integer $x * @param integer $y * @param integer $width * @param integer $height * @param integer $start * @param integer $end * @param array $colour * @param float $opacity * @param boolean $outline * * @return $this * @see http://www.php.net/manual/en/function.imagefilledarc.php */ public function arc ( $x = 0, $y = 0, $width = 100, $height = 50, $start = 0, $end = 180, $colour = [ 0, 0, 0 ], $opacity = 1.0, $outline = FALSE ) { if ( $outline === TRUE ) { imagearc( $this->img, $x, $y, $width, $height, $start, $end, imagecolorallocatealpha( $this->img, $colour[ 0 ], $colour[ 1 ], $colour[ 2 ], ( 1 - $opacity ) * 127 ) ); } else { imagefilledarc( $this->img, $x, $y, $width, $height, $start, $end, imagecolorallocatealpha( $this->img, $colour[ 0 ], $colour[ 1 ], $colour[ 2 ], ( 1 - $opacity ) * 127 ), IMG_ARC_PIE ); } $this->afterUpdate(); return $this; } /** * Draw an image from file * * Accepts x/y properties from CSS background-position (left, center, right, top, bottom, percentage and pixels) * * @param String $file * @param String|integer $x * @param String|integer $y * * @return $this * @see http://www.w3schools.com/cssref/pr_background-position.asp * @see http://www.php.net/manual/en/function.imagecopyresampled.php */ public function draw ( $file, $x = '50%', $y = '50%', $wr = NULL, $hr = NULL ) { if ( $info = $this->getImageInfo( $file ) ) { $image = $info->resource; $width = $info->width; $height = $info->height; if ( is_null( $wr ) ) { $wr = $width; $hr = $height; } // Defaults if invalid values passed if ( strpos( $x, '%' ) === FALSE && ! is_numeric( $x ) && ! in_array( $x, [ 'left', 'center', 'right' ] ) ) { $x = '50%'; } if ( strpos( $y, '%' ) === FALSE && ! is_numeric( $y ) && ! in_array( $y, [ 'top', 'center', 'bottom' ] ) ) { $y = '50%'; } // If word passed, convert it to percentage switch ( $x ) { case 'left': $x = '0%'; break; case 'center': $x = '50%'; break; case 'right': $x = '100%'; break; } switch ( $y ) { case 'top': $y = '0%'; break; case 'center': $y = '50%'; break; case 'bottom': $y = '100%'; break; } // Work out offset if ( strpos( $x, '%' ) > -1 ) { $x = str_replace( '%', '', $x ); $x = ceil( ( $this->width - $width ) * ( $x / 100 ) ); } if ( strpos( $y, '%' ) > -1 ) { $y = str_replace( '%', '', $y ); $y = ceil( ( $this->height - $height ) * ( $y / 100 ) ); } // Draw image imagecopyresampled( $this->img, $image, $x + ( $width - $wr ) / 2, $y + ( $height - $hr ) / 2, 0, 0, $wr, $hr, $width, $height ); imagedestroy( $image ); $this->afterUpdate(); return $this; } else { $this->handleError( $file . ' is not a valid image!' ); } } /** * Draw text * * ### Options * * - integer $fontSize * - integer $x * - integer $y * - integer $angle * - integer $strokeWidth * - float $opacity * - array $fontColor * - array $strokeColor * - String $fontFile * * @param String $text * @param array $options * * @return $this * @see http://www.php.net/manual/en/function.imagefttext.php */ public function text ( $text, $options = [] ) { // Unset null values so they inherit defaults foreach ( $options as $k => $v ) { if ( $options[ $k ] === NULL ) { unset( $options[ $k ] ); } } $defaults = [ 'fontSize' => $this->fontSize, 'fontColor' => $this->textColor, 'opacity' => $this->textOpacity, 'x' => 0, 'y' => 0, 'width' => NULL, 'height' => NULL, 'alignHorizontal' => $this->alignHorizontal, 'alignVertical' => $this->alignVertical, 'angle' => $this->textAngle, 'strokeWidth' => $this->strokeWidth, 'strokeColor' => $this->strokeColor, 'fontFile' => $this->fontFile, 'autoFit' => TRUE, 'debug' => FALSE ]; extract( array_merge( $defaults, $options ), EXTR_OVERWRITE ); if ( $fontFile === NULL ) { $this->handleError( 'No font file set!' ); } if ( is_int( $width ) && $autoFit ) { $fontSize = $this->fitToWidth( $fontSize, $angle, $fontFile, $text, $width ); } $lines = explode( "\n", $text ); if ( $debug && is_int( $width ) && is_int( $height ) ) { $this->rectangle( $x, $y, $width, $height, [ 0, 255, 255 ], 0.5 ); } $fontHeight = $this->getFontHeight( $fontSize, $angle, $fontFile, $lines ); $lineHeight = $fontHeight * $this->lineHeight; foreach ( $lines as $index => $line ) { // Get Y offset as it 0 Y is the lower-left corner of the character $testbox = imageftbbox( $fontSize, $angle, $fontFile, $line ); $offsety = abs( $testbox[ 7 ] ); $offsetx = 0; $actualWidth = abs( $testbox[ 6 ] - $testbox[ 4 ] ); $actualHeight = $lineHeight; $lineY = $y + ( $lineHeight * $index ); // If text box align text if ( is_int( $width ) || is_int( $height ) ) { if ( ! is_int( $width ) ) { $width = $actualWidth; } if ( ! is_int( $height ) ) { $height = $actualHeight; } switch ( $alignHorizontal ) { case 'center': $offsetx += ( ( $width - $actualWidth ) / 2 ); break; case 'right': $offsetx += ( $width - $actualWidth ); break; } switch ( $alignVertical ) { case 'center': $offsety += ( ( $height - ( $lineHeight * count( $lines ) ) ) / 2 ); break; case 'bottom': $offsety += ( $height - ( $lineHeight * count( $lines ) ) ); break; } if ( $debug ) { $this->rectangle( $x + $offsetx, $lineY + $offsety - $fontHeight, $actualWidth, $lineHeight, [ rand( 150, 255 ), rand( 150, 255 ), rand( 150, 255 ) ], 0.5 ); } } // Draw stroke if ( $strokeWidth > 0 ) { $tmpStrokeColor = imagecolorallocatealpha( $this->img, $strokeColor[ 0 ], $strokeColor[ 1 ], $strokeColor[ 2 ], ( 1 - $opacity ) * 127 ); for ( $sx = ( $x - abs( $strokeWidth ) ); $sx <= ( $x + abs( $strokeWidth ) ); $sx++ ) { for ( $sy = ( $lineY - abs( $strokeWidth ) ); $sy <= ( $lineY + abs( $strokeWidth ) ); $sy++ ) { imagefttext( $this->img, $fontSize, $angle, $sx + $offsetx, $sy + $offsety, $tmpStrokeColor, $fontFile, $line ); } } } // Draw text imagefttext( $this->img, $fontSize, $angle, $x + $offsetx, $lineY + $offsety, imagecolorallocatealpha( $this->img, $fontColor[ 0 ], $fontColor[ 1 ], $fontColor[ 2 ], ( 1 - $opacity ) * 127 ), $fontFile, $line ); } $this->afterUpdate(); return $this; } /** * Reduce font size to fit to width * * @param integer $fontSize * @param integer $angle * @param String $fontFile * @param String $text * @param integer $width * * @return integer */ protected function fitToWidth ( $fontSize, $angle, $fontFile, $text, $width ) { while ( $fontSize > 0 ) { $testbox = imageftbbox( $fontSize, $angle, $fontFile, $text ); $actualWidth = abs( $testbox[ 6 ] - $testbox[ 4 ] ); if ( $actualWidth <= $width ) { return $fontSize; } else { $fontSize--; } } return $fontSize; } /** * Reduce font size to fit to width and height * * @param integer $fontSize * @param integer $angle * @param String $fontFile * @param String $text * @param integer $width * @param integer $height * * @return integer */ protected function fitToBounds ( $fontSize, $angle, $fontFile, $text, $width, $height ) { while ( $fontSize > 0 ) { $wrapped = $this->wrap( $text, $width, $fontSize, $angle, $fontFile ); $testbox = imageftbbox( $fontSize, $angle, $fontFile, $wrapped ); $actualHeight = abs( $testbox[ 1 ] - $testbox[ 7 ] ); if ( $actualHeight <= $height ) { return $fontSize; } else { $fontSize--; } } return $fontSize; } /** * Get font height * * @param integer $fontSize * @param integer $angle * @param String $fontFile * @param array lines * * @return integer */ protected function getFontHeight ( $fontSize, $angle, $fontFile, $lines ) { $height = 0; foreach ( $lines as $index => $line ) { $testbox = imageftbbox( $fontSize, $angle, $fontFile, $line ); $actualHeight = abs( $testbox[ 1 ] - $testbox[ 7 ] ); if ( $actualHeight > $height ) { $height = $actualHeight; } } return $height; } /** * Draw multi-line text box and auto wrap text * * @param String $text * @param array $options * * @return $this */ public function textBox ( $text, $options = [] ) { $defaults = [ 'fontSize' => $this->fontSize, 'fontColor' => $this->textColor, 'opacity' => $this->textOpacity, 'x' => 0, 'y' => 0, 'width' => 100, 'height' => NULL, 'angle' => $this->textAngle, 'strokeWidth' => $this->strokeWidth, 'strokeColor' => $this->strokeColor, 'fontFile' => $this->fontFile, 'debug' => FALSE, 'alignHorizontal' => $this->alignHorizontal, 'alignVertical' => $this->alignVertical ]; extract( array_merge( $defaults, $options ), EXTR_OVERWRITE ); if ( $height ) { $fontSize = $this->fitTobounds( $fontSize, $angle, $fontFile, $text, $width, $height ); } return $this->text( $this->wrap( $text, $width, $fontSize, $angle, $fontFile ), [ 'fontSize' => $fontSize, 'x' => $x, 'y' => $y, 'width' => $width, 'height' => $height, 'angle' => $angle, 'strokeWidth' => $strokeWidth, 'opacity' => $opacity, 'fontColor' => $fontColor, 'strokeColor' => $strokeColor, 'fontFile' => $fontFile, 'alignHorizontal' => $alignHorizontal, 'alignVertical' => $alignVertical, 'debug' => $debug ] ); } /** * Helper to wrap text * * @param String $text * @param integer $width * @param integer $fontSize * @param integer $angle * @param String $fontFile * * @return String */ protected function wrap ( $text, $width = 100, $fontSize = 12, $angle = 0, $fontFile = NULL ) { if ( $fontFile === NULL ) { $fontFile = $this->fontFile; } $ret = ""; $arr = explode( ' ', $text ); foreach ( $arr as $word ) { $teststring = $ret . ' ' . $word; $testbox = imageftbbox( $fontSize, $angle, $fontFile, $teststring ); if ( $testbox[ 2 ] > $width ) { $ret .= ( $ret == "" ? "" : "\n" ) . $word; } else { $ret .= ( $ret == "" ? "" : ' ' ) . $word; } } return $ret; } /** * Check quality is correct before save * * @return $this */ public function checkQuality () { switch ( $this->type ) { case IMAGETYPE_JPEG: if ( $this->quality > 100 ) { $this->quality = 100; } else if ( $this->quality < 0 ) { $this->quality = 0; } else if ( $this->quality >= 0 && $this->quality <= 100 ) { } else { $this->quality = 75; } break; case IMAGETYPE_PNG: if ( $this->quality > 9 ) { $this->quality = 9; } else if ( $this->quality < 0 ) { $this->quality = 0; } else if ( $this->quality >= 0 && $this->quality <= 9 ) { } else { $this->quality = 6; } break; } return $this; } /** * Set's global folder mode if folder structure needs to be created * * @param integer $mode * * @return $this */ public function setFolderMode ( $mode = 0755 ) { $this->folderMode = $mode; return $this; } /** * Set's global text size * * @param integer $size * * @return $this */ public function setFontSize ( $size = 12 ) { $this->fontSize = $size; return $this; } /** * Set's global line height * * @param float $lineHeight * * @return $this */ public function setLineHeight ( $lineHeight = 1.25 ) { $this->lineHeight = $lineHeight; return $this; } /** * Set's global text vertical alignment * * @param String $align * * @return $this */ public function setAlignVertical ( $align = 'top' ) { $this->alignVertical = $align; return $this; } /** * Set's global text horizontal alignment * * @param String $align * * @return $this */ public function setAlignHorizontal ( $align = 'left' ) { $this->alignHorizontal = $align; return $this; } /** * Set's global text colour using RGB * * @param array $colour * * @return $this */ public function setTextColor ( $colour = [ 255, 255, 255 ] ) { $this->textColor = $colour; return $this; } /** * Set's global text angle * * @param integer $angle * * @return $this */ public function setTextAngle ( $angle = 0 ) { $this->textAngle = $angle; return $this; } /** * Set's global text stroke * * @param integer $strokeWidth * * @return $this */ public function setStrokeWidth ( $strokeWidth = 0 ) { $this->strokeWidth = $strokeWidth; return $this; } /** * Set's global text opacity * * @param float $opacity * * @return $this */ public function setTextOpacity ( $opacity = 1.0 ) { $this->textOpacity = $opacity; return $this; } /** * Set's global stroke colour * * @param array $colour * * @return $this */ public function setStrokeColor ( $colour = [ 0, 0, 0 ] ) { $this->strokeColor = $colour; return $this; } /** * Set's global font file for text from .ttf font file (TrueType) * * @param string $fontFile * * @return $this */ public function setFont ( $fontFile ) { $this->fontFile = $fontFile; return $this; } /** * Set's global quality for PNG output * * @param string $quality * * @return $this */ public function setQuality ( $quality ) { $this->quality = $quality; return $this; } /** * Set's global output type * * @param String $type * @param String $quality * * @return $this */ public function setOutput ( $type, $quality = NULL ) { switch ( strtolower( $type ) ) { case 'gif': $this->type = IMAGETYPE_GIF; break; case 'jpg': $this->type = IMAGETYPE_JPEG; break; case 'png': $this->type = IMAGETYPE_PNG; break; } if ( $quality !== NULL ) { $this->setQuality( $quality ); } return $this; } }
| ver. 1.4 |
Github
|
.
| PHP 8.0.30 | Generation time: 0.06 |
proxy
|
phpinfo
|
Settings