3v4l.org

run code in 300+ PHP versions simultaneously
<?php class Image{ public $filepath; public $width; public $height; public $mime; public $landscape; public $imageFunct; public $compression; // Image resource identifier private $image; // Is it a temporary image private $isTemp; /** * constructor * @param type $fp * @param type $isTemp - if true, will delete the image file on the destroy call * @throws Exception */ public function __construct($fp, $isTemp = false){ // Make sure file exists if(!file_exists($fp)) throw new Exception("Image source file does not exist: $fp"); $this->isTemp = $isTemp; $this->filepath = $fp; $data = getimagesize($fp); $this->width = $data[0]; $this->height = $data[1]; $this->landscape = $this->width > $this->height; $this->mime = $data['mime']; switch($this->mime){ case("image/png"): $this->image = imagecreatefrompng($this->filepath); imagealphablending($this->image, false); imagesavealpha($this->image, true); $this->imageFunct = 'imagepng'; $this->compression = 9; break; case('image/jpeg'): case('image/pjpeg'): case('image/x-jps'): $this->image = imagecreatefromjpeg($this->filepath); $this->imageFunct = 'imagejpeg'; $this->compression = 100; break; case('image/gif'): $this->image = imagecreatefromgif($this->filepath); imagealphablending($this->image, false); imagesavealpha($this->image, true); $this->imageFunct = 'imagegif'; break; default: throw new Exception("Invalid image type. Only excepts PNG, JPG, and GIF. You entered a {$this->mime} type image."); } } /** * scales the image to cover the dimensions provided * @param type $width (of canvas) * @param type $height (of canvas) */ public function scale($width, $height, $cover='fill'){ // Get new dimensions $imgRatio = $this->height/$this->width; $canvasRatio = $height/$width; if( ($canvasRatio > $imgRatio && $cover=='fill') || ($canvasRatio <= $imgRatio && $cover!='fill') ){ $finalHeight = $height; $scale = $finalHeight / $this->height; $finalWidth = $this->width * $scale; }else{ $finalWidth = $width; $scale = $finalWidth / $this->width; $finalHeight = $this->height * $scale; } // Resize the image $thumb = imagecreatetruecolor($finalWidth, $finalHeight); imagealphablending($thumb, false); imagesavealpha($thumb, true); imagecopyresampled($thumb, $this->image, 0, 0, 0, 0, $finalWidth, $finalHeight, $this->width, $this->height); $this->resize($finalWidth, $finalHeight); $this->width = $finalWidth; $this->height = $finalHeight; } /** * scales the image to cover the dimensions provided * @param type $width (of canvas) * @param type $height (of canvas) */ public function resize($width, $height){ // Resize the image $thumb = imagecreatetruecolor($width, $height); imagealphablending($thumb, false); imagesavealpha($thumb, true); imagecopyresampled($thumb, $this->image, 0, 0, 0, 0, $width, $height, $this->width, $this->height); $this->image = $thumb; $this->width = $width; $this->height = $height; } /** * tile the image to the provided dimensions * @param type $width * @param type $height * @param type $output_mimetype */ public function tile($width, $height){ // Our output image to be created $out = imagecreatetruecolor($width, $this->height); imagealphablending($out, false); imagesavealpha($out, true); // Tile that shit horiz $curr_x = 0; while($curr_x < $width){ imagecopy($out, $this->image, $curr_x, 0, 0, 0, $this->width, $this->height); $curr_x += $this->width; } // our final output image to be created $thumb = imagecreatetruecolor($width, $height); imagealphablending($thumb, false); imagesavealpha($thumb, true); // Tile that shit vert $curr_y = 0; while($curr_y < $height){ imagecopy($thumb, $out, 0, $curr_y, 0, 0, $width, $this->height); $curr_y += $this->height; } imagedestroy($out); $this->image = $thumb; } /** * Reverse all colors of the image */ public function reverseColors(){ return imagefilter($this->image, IMG_FILTER_NEGATE); } /** * Convert image to greyscale */ public function greyScale(){ return imagefilter($this->image, IMG_FILTER_GRAYSCALE); } /** * Adjust brightness level. (between 255 and -255) * @param type $brightness */ public function adjustBrightness($brightness){ if($brightness > 255) $brightness = 255; if($brightness < -255) $brightness = -255; return imagefilter($this->image, IMG_FILTER_BRIGHTNESS, $brightness); } /** * Adjust the contrast level * @param int $contrast */ public function adjustContrast($contrast){ return imagefilter($this->image, IMG_FILTER_CONTRAST, $contrast); } /** * Turns on edgeDetect Filter */ public function edgeDetect(){ return imagefilter($this->image, IMG_FILTER_EDGEDETECT); } /** * Turns on emboss Filter */ public function emboss(){ return imagefilter($this->image, IMG_FILTER_EMBOSS); } /** * Turns on gaussianBlur Filter */ public function gaussianBlur(){ return imagefilter($this->image, IMG_FILTER_GAUSSIAN_BLUR); } /** * Turns on selectiveBlur Filter */ public function selectiveBlur(){ return imagefilter($this->image, IMG_FILTER_SELECTIVE_BLUR); } /** * Turns on sketch Filter */ public function sketch(){ return imagefilter($this->image, IMG_FILTER_MEAN_REMOVAL); } /** * Adds a vignette */ function vignette(){ for($x = 0; $x < imagesx($this->image); ++$x){ for($y = 0; $y < imagesy($this->image); ++$y){ $index = imagecolorat($this->image, $x, $y); $rgb = imagecolorsforindex($this->image, $index); $sharp = 0.4; // 0 - 10 small is sharpnes, $level = 0.7; // 0 - 1 small is brighter $l = sin(M_PI / $this->width * $x) * sin(M_PI / $this->height * $y); $l = pow($l, $sharp); $l = 1 - $level * (1 - $l); $rgb['red'] *= $l; $rgb['green'] *= $l; $rgb['blue'] *= $l; $color = imagecolorallocate($this->image, $rgb['red'], $rgb['green'], $rgb['blue']); imagesetpixel($this->image, $x, $y, $color); } } return true; } /** * Pixelate the image * @param type $blocksize * @param type $advanced */ public function pixelate($blocksize, $advanced=true){ return imagefilter($this->image, IMG_FILTER_PIXELATE, $blocksize, $advanced); } /** * Adjust smoothness level * @param type $level */ public function adjustSmoothness($level){ return imagefilter($this->image, IMG_FILTER_SMOOTH, $level); } /** * Colorize an image * @param type $hexColor */ public function colorize($hexColor, $alpha){ list($r, $g, $b) = self::convertHexColor($hexColor); if($alpha < 0) $alpha = 0; if($alpha > 127) $alpha = 127; return imagefilter($this->image, IMG_FILTER_COLORIZE, $r, $g, $b, $alpha); } /** * Outputs the image directly to the browser * @param type $output_mimetype ("png", "jpg", or "gif") * (defaults to the original image's mimtype) */ public function output($output_mimetype = null){ // Get output details list($mimetype, $funct, $compression) = $this->getOutputDetails($output_mimetype); // Output and clear memory header('Content-Type: '.$mimetype); // Get and call the image creation funtion $funct($this->image, null, $compression); } /** * Destroys the generated image to free up resources, * Delete the file if it's a temporary file. * should be the last method called as the object is unusable after this. */ public function destroy(){ imagedestroy($this->image); if($this->isTemp) unlink($this->filepath); } /** * Crops the image to the given dimensions, at the given starting point * defaults to the top left * @param type $width * @param type $height * @param type $x * @param type $y */ public function crop($new_width, $new_height, $x = 0, $y = 0){ // Get dimensions $width = imagesx($this->image); $height = imagesy($this->image); // Make the dummy image that will become the new image $newImg = imagecreatetruecolor($new_width, $new_height); // Fill with transparent background imagealphablending($newImg, false); imagesavealpha($newImg, true); $transparent = imagecolorallocatealpha($newImg, 255, 255, 255, 127); imagefilledrectangle($newImg, 0, 0, $new_width, $new_height, $transparent); // Copy the pixels to the new image imagecopy($newImg, $this->image, 0, 0, 0, 0, $width, $height); $this->image = $newImg; $this->width = $width; $this->height = $height; } /** * Create an image from a base64 string * @param type $string * @return \Image */ public static function createFromBase64($string){ // decode base64 string $imgData = base64_decode(preg_replace('#^data:image/\w+;base64,#i', '', $string)); // create the image resource $formImage = imagecreatefromstring($imgData); // Fill with transparent background imagealphablending($formImage, false); imagesavealpha($formImage, true); $transparent = imagecolorallocatealpha($formImage, 255, 255, 255, 127); imagefill($formImage, 0, 0, $transparent); // Save the image to a temp png file to use in our constructor $tmpname = tempnam('/tmp', 'IMG'); // Generate and save image imagepng($formImage, $tmpname, 9); // Return an instance of the class $img = new Image($tmpname, true); return $img; } /** * Make an image of text * @param type $text * @param type $size * @param type $color * @param type $font */ public static function createTextImage($text, $font_size, $color, $font_file, $wrap_width = false){ // Make sure font file exists //if(!file_exists($font_file)) throw new Exception("Font file does not exist: {$font_file}"); // Generate wrapping text if(is_numeric($wrap_width) && $wrap_width != 0) $text = self::wrapText($font_size, $font_file, $text, $wrap_width); // Retrieve bounding box: $type_space = imagettfbbox($font_size, 0, $font_file, $text); // Determine image width and height, 10 pixels are added for 5 pixels padding: $image_width = abs($type_space[4] - $type_space[0]) + 10; $image_height = abs($type_space[5] - $type_space[1]) + 10; $line_height = self::getLineHeight($font_size, $font_file) +10; // Create image: $image = imagecreatetruecolor($image_width, $image_height); // Allocate text and background colors (RGB format): $text_color = self::getColor($image, $color); // Fill with transparent background imagealphablending($image, false); imagesavealpha($image, true); $transparent = imagecolorallocatealpha($image, 255, 255, 255, 127); imagefill($image, 0, 0, $transparent); // Fix starting x and y coordinates for the text: $x = 5; // Padding of 5 pixels. $y = $line_height - 5; // So that the text is vertically centered. // Add TrueType text to image: imagettftext($image, $font_size, 0, $x, $y, $text_color, $font_file, $text); // Save the image to a temp png file to use in our constructor $tmpname = tempnam('/tmp', 'IMG'); // Generate and save image imagepng($image, $tmpname, 9); // Return an instance of the class $img = new Image($tmpname, true); $img->crop($image_width, $image_height); return $img; } /** * Get output information * @param type $output_mimetype * @return array($mimetype, $output_funct, $compression) */ private function getOutputDetails($output_mimetype){ switch(strtoupper($output_mimetype)){ case('JPG'): case('JPEG'): $mimetype = 'image/jpeg'; $funct = 'imagejpeg'; $compression = 100; break; case('PNG'): $mimetype = 'image/png'; $funct = 'imagepng'; $compression = 9; break; case('GIF'): $mimetype = 'image/gif'; $funct = 'imagegif'; $compression = null; break; default: $mimetype = $this->mime; $funct = $this->imageFunct; $compression = $this->compression; } return array($mimetype, $funct, $compression); } private static function convertHexColor($hex){ // Remove the # if therre is one $hex = str_replace("#", "", $hex); // Convert the hex to rgb if(strlen($hex) == 3){ $r = hexdec(substr($hex, 0, 1) . substr($hex, 0, 1)); $g = hexdec(substr($hex, 1, 1) . substr($hex, 1, 1)); $b = hexdec(substr($hex, 2, 1) . substr($hex, 2, 1)); }else{ $r = hexdec(substr($hex, 0, 2)); $g = hexdec(substr($hex, 2, 2)); $b = hexdec(substr($hex, 4, 2)); } return array($r, $g, $b); } /** * Convert Hex Colors To RGB * @param type $image - image identifier * @param type $hex - the hex color code * @param type $alpha - 0 for solid - 127 for transparent * @return type color identifier * @throws Exception */ private static function getColor($image, $hex, $alpha=0){ list($r, $g, $b) = self::convertHexColor($hex); // The alpha layer seems to make things gritty, // so let's avoid it if there's no transparency $return = ($alpha==0) ? imagecolorallocatealpha($image, $r, $g, $b, $alpha) : imagecolorallocate($image, $r, $g, $b) ; // Make sure it worked if($return === false) throw new Exception("Could not create color $hex."); return $return; } /** * Inserts linebreaks to wrap text * @param type $fontSize * @param type $fontFace * @param type $string * @param type $width * @return string */ private static function wrapText($fontSize, $fontFace, $string, $width){ $ret = ""; $arr = explode(" ", $string); foreach($arr as $word){ $testboxWord = imagettfbbox($fontSize, 0, $fontFace, $word); // huge word larger than $width, we need to cut it internally until it fits the width $len = strlen($word); while($testboxWord[2] > $width && $len > 0){ $word = substr($word, 0, $len); $len--; $testboxWord = imagettfbbox($fontSize, 0, $fontFace, $word); } $teststring = $ret . ' ' . $word; $testboxString = imagettfbbox($fontSize, 0, $fontFace, $teststring); if($testboxString[2] > $width){ $ret.=($ret == "" ? "" : "\n") . $word; }else{ $ret.=($ret == "" ? "" : ' ') . $word; } } return $ret; } /** * Returns the line height based on the font and font size * @param type $fontSize * @param type $fontFace */ private static function getLineHeight($fontSize, $fontFace){ // Arbitrary text is drawn, can't be blank or just a space $type_space = imagettfbbox($fontSize, 0, $fontFace, "Robert is awesome!"); $line_height = abs($type_space[5] - $type_space[1]); return $line_height; } } $text = "This is a test"; $ttf_font_file = "https://cdnjs.cloudflare.com/ajax/libs/font-awesome/4.5.0/fonts/fontawesome-webfont.ttf"; $font_size = 50; $color = "#000"; $img = Image::createTextImage($text, $font_size, $color, $ttf_font_file); $img->pixelate($blocksize); $img->output('png');

preferences:
31.24 ms | 402 KiB | 5 Q