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');

Here you find the average performance (time & memory) of each version. A grayed out version indicates it didn't complete successfully (based on exit-code).

VersionSystem time (s)User time (s)Memory (MiB)
8.3.60.0120.00918.68
8.3.50.0120.00921.13
8.3.40.0090.00618.88
8.3.30.0110.01118.79
8.3.20.0030.00520.58
8.3.10.0050.00323.66
8.3.00.0060.00323.67
8.2.180.0090.01318.41
8.2.170.0040.01219.34
8.2.160.0180.00422.96
8.2.150.0060.00924.18
8.2.140.0030.00524.66
8.2.130.0030.00619.62
8.2.120.0030.00526.35
8.2.110.0060.00320.94
8.2.100.0160.00018.03
8.2.90.0030.00519.52
8.2.80.0060.00318.00
8.2.70.0140.00217.88
8.2.60.0000.00818.05
8.2.50.0030.00618.07
8.2.40.0030.00622.15
8.2.30.0050.00320.84
8.2.20.0000.00818.04
8.2.10.0000.00818.41
8.2.00.0050.00318.34
8.1.280.0100.00725.92
8.1.270.0120.00620.45
8.1.260.0100.01028.09
8.1.250.0090.00928.09
8.1.240.0000.01022.29
8.1.230.0150.00019.16
8.1.220.0000.00918.01
8.1.210.0060.00318.77
8.1.200.0030.00617.61
8.1.190.0030.01017.11
8.1.180.0030.00618.10
8.1.170.0000.00918.70
8.1.160.0080.00021.01
8.1.150.0030.00619.07
8.1.140.0060.00319.68
8.1.130.0040.00417.93
8.1.120.0060.00317.64
8.1.110.0040.00417.70
8.1.100.0040.00417.62
8.1.90.0080.00017.73
8.1.80.0040.00417.69
8.1.70.0030.00517.61
8.1.60.0090.00017.70
8.1.50.0040.00417.71
8.1.40.0030.00617.70
8.1.30.0030.00617.82
8.1.20.0030.00517.88
8.1.10.0000.00917.77
8.1.00.0030.00617.69
8.0.300.0060.00320.29
8.0.290.0040.00417.00
8.0.280.0040.00418.65
8.0.270.0040.00417.40
8.0.260.0030.00317.41
8.0.250.0080.00017.25
8.0.240.0000.00817.19
8.0.230.0030.00617.24
8.0.220.0040.00417.09
8.0.210.0060.00317.16
8.0.200.0070.00017.11
8.0.190.0040.00417.15
8.0.180.0030.00617.12
8.0.170.0040.00417.11
8.0.160.0000.00817.21
8.0.150.0080.00017.12
8.0.140.0030.00617.01
8.0.130.0070.00013.64
8.0.120.0040.00417.21
8.0.110.0030.00517.20
8.0.100.0040.00417.22
8.0.90.0040.00417.05
8.0.80.0070.01017.14
8.0.70.0000.00817.09
8.0.60.0000.00817.20
8.0.50.0000.00817.19
8.0.30.0140.00917.40
8.0.20.0130.00617.48
8.0.10.0050.00317.34
8.0.00.0120.01017.25
7.4.330.0030.00316.66
7.4.320.0000.00616.82
7.4.300.0070.00016.74
7.4.290.0000.00716.84
7.4.280.0030.00316.73
7.4.270.0040.00416.86
7.4.260.0000.00816.73
7.4.250.0000.00816.70
7.4.240.0020.00616.74
7.4.230.0040.00416.92
7.4.220.0060.01216.74
7.4.210.0100.00616.93
7.4.200.0030.00516.56
7.4.160.0080.00816.72
7.4.150.0060.01217.40
7.4.140.0060.01317.86
7.4.130.0090.01016.75
7.4.120.0100.00916.83
7.4.110.0060.01416.80
7.4.100.0140.01016.71
7.4.90.0070.01116.83
7.4.80.0150.00919.39
7.4.70.0170.00316.71
7.4.60.0110.00616.72
7.4.50.0040.01116.82
7.4.40.0030.01516.43
7.4.30.0140.00416.74
7.4.00.0090.00815.19
7.3.330.0000.00513.46
7.3.320.0050.00013.49
7.3.310.0040.00416.49
7.3.300.0070.00016.52
7.3.290.0110.00616.66
7.3.280.0090.01216.64
7.3.270.0070.01117.40
7.3.260.0070.01116.80
7.3.250.0130.00716.72
7.3.240.0090.01016.62
7.3.230.0090.00916.72
7.3.210.0070.01116.91
7.3.200.0130.01116.71
7.3.190.0070.01416.71
7.3.180.0060.01716.56
7.3.170.0100.00716.72
7.3.160.0090.00916.73
7.3.120.0070.01315.02
7.3.110.0030.01614.98
7.3.100.0000.01314.78
7.3.90.0100.00714.82
7.3.80.0000.01215.00
7.3.70.0000.01115.23
7.3.60.0060.00315.07
7.3.50.0060.00614.90
7.3.40.0070.00314.90
7.3.30.0050.00515.14
7.3.20.0060.00916.86
7.3.10.0000.01316.45
7.3.00.0060.00916.84
7.2.330.0060.02016.89
7.2.320.0140.01016.59
7.2.310.0000.01816.90
7.2.300.0090.01216.82
7.2.290.0100.00716.89
7.2.250.0040.01915.04
7.2.240.0060.01515.14
7.2.230.0070.01015.33
7.2.220.0000.01015.08
7.2.210.0000.01414.87
7.2.200.0070.00715.36
7.2.190.0030.01015.15
7.2.180.0100.00315.23
7.2.170.0070.00714.86
7.2.60.0090.00616.88
7.2.00.0040.00719.48
7.1.330.0030.01215.93
7.1.320.0070.00015.97
7.1.310.0070.00315.97
7.1.300.0050.00315.63
7.1.290.0040.00715.87
7.1.280.0000.00815.75
7.1.270.0070.00715.54
7.1.260.0030.01215.81
7.1.200.0050.00515.79
7.1.100.0060.00617.76
7.1.70.0000.00917.35
7.1.60.0100.01419.52
7.1.50.0060.00817.01
7.1.00.0030.07722.54
7.0.200.0000.00816.84
7.0.100.0000.04320.15
7.0.90.0130.03320.13
7.0.80.0130.05020.20
7.0.70.0170.06720.16
7.0.60.0070.04020.16
7.0.50.0030.08020.48
7.0.40.0130.07020.15
7.0.30.0130.07320.05
7.0.20.0100.08020.10
7.0.10.0030.08720.03
7.0.00.0130.07320.03
5.6.280.0030.07021.04
5.6.250.0070.03720.71
5.6.240.0170.03020.84
5.6.230.0030.04320.80
5.6.220.0100.06020.70
5.6.210.0030.05020.68
5.6.200.0030.08321.23
5.6.190.0070.07721.13
5.6.180.0030.07021.15
5.6.170.0130.07721.13
5.6.160.0070.08721.13
5.6.150.0000.08321.29
5.6.140.0030.09021.12
5.6.130.0130.08021.16
5.6.120.0100.08021.22
5.6.110.0200.07021.07
5.6.100.0200.07721.14
5.6.90.0000.09021.05
5.6.80.0030.08320.61
5.6.70.0030.08320.67
5.6.60.0130.07320.43
5.6.50.0100.04720.45
5.6.40.0130.07320.41
5.6.30.0070.07020.52
5.6.20.0130.07320.46
5.6.10.0130.08020.53
5.6.00.0030.07720.57
5.5.380.0000.05020.64
5.5.370.0000.04720.47
5.5.360.0100.07720.45
5.5.350.0030.08320.59
5.5.340.0130.07021.01
5.5.330.0030.08720.92
5.5.320.0170.08020.96
5.5.310.0130.07020.96
5.5.300.0070.08321.01
5.5.290.0170.07320.95
5.5.280.0200.04020.98
5.5.270.0130.08020.98
5.5.260.0070.08721.04
5.5.250.0030.06720.82
5.5.240.0200.06720.42
5.5.230.0000.08720.38
5.5.220.0170.06320.42
5.5.210.0070.08020.37
5.5.200.0030.08320.23
5.5.190.0000.09020.27
5.5.180.0200.06720.27
5.5.160.0070.08020.33
5.5.150.0070.04320.22
5.5.140.0000.08320.35
5.5.130.0070.04720.20
5.5.120.0100.07720.22
5.5.110.0100.07020.39
5.5.100.0070.08020.19
5.5.90.0070.07720.19
5.5.80.0130.07020.16
5.5.70.0070.08020.08
5.5.60.0070.08320.23
5.5.50.0100.07720.25
5.5.40.0030.05020.17
5.5.30.0100.06320.11
5.5.20.0100.07020.18
5.5.10.0030.08320.24
5.5.00.0100.08020.08

preferences:
58.61 ms | 401 KiB | 5 Q