@ 2015-12-10T15:20:46Z <?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');
Enable javascript to submit You have javascript disabled. You will not be able to edit any code.
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).
Version System time (s) User time (s) Memory (MiB) 8.3.6 0.012 0.009 18.68 8.3.5 0.012 0.009 21.13 8.3.4 0.009 0.006 18.88 8.3.3 0.011 0.011 18.79 8.3.2 0.003 0.005 20.58 8.3.1 0.005 0.003 23.66 8.3.0 0.006 0.003 23.67 8.2.18 0.009 0.013 18.41 8.2.17 0.004 0.012 19.34 8.2.16 0.018 0.004 22.96 8.2.15 0.006 0.009 24.18 8.2.14 0.003 0.005 24.66 8.2.13 0.003 0.006 19.62 8.2.12 0.003 0.005 26.35 8.2.11 0.006 0.003 20.94 8.2.10 0.016 0.000 18.03 8.2.9 0.003 0.005 19.52 8.2.8 0.006 0.003 18.00 8.2.7 0.014 0.002 17.88 8.2.6 0.000 0.008 18.05 8.2.5 0.003 0.006 18.07 8.2.4 0.003 0.006 22.15 8.2.3 0.005 0.003 20.84 8.2.2 0.000 0.008 18.04 8.2.1 0.000 0.008 18.41 8.2.0 0.005 0.003 18.34 8.1.28 0.010 0.007 25.92 8.1.27 0.012 0.006 20.45 8.1.26 0.010 0.010 28.09 8.1.25 0.009 0.009 28.09 8.1.24 0.000 0.010 22.29 8.1.23 0.015 0.000 19.16 8.1.22 0.000 0.009 18.01 8.1.21 0.006 0.003 18.77 8.1.20 0.003 0.006 17.61 8.1.19 0.003 0.010 17.11 8.1.18 0.003 0.006 18.10 8.1.17 0.000 0.009 18.70 8.1.16 0.008 0.000 21.01 8.1.15 0.003 0.006 19.07 8.1.14 0.006 0.003 19.68 8.1.13 0.004 0.004 17.93 8.1.12 0.006 0.003 17.64 8.1.11 0.004 0.004 17.70 8.1.10 0.004 0.004 17.62 8.1.9 0.008 0.000 17.73 8.1.8 0.004 0.004 17.69 8.1.7 0.003 0.005 17.61 8.1.6 0.009 0.000 17.70 8.1.5 0.004 0.004 17.71 8.1.4 0.003 0.006 17.70 8.1.3 0.003 0.006 17.82 8.1.2 0.003 0.005 17.88 8.1.1 0.000 0.009 17.77 8.1.0 0.003 0.006 17.69 8.0.30 0.006 0.003 20.29 8.0.29 0.004 0.004 17.00 8.0.28 0.004 0.004 18.65 8.0.27 0.004 0.004 17.40 8.0.26 0.003 0.003 17.41 8.0.25 0.008 0.000 17.25 8.0.24 0.000 0.008 17.19 8.0.23 0.003 0.006 17.24 8.0.22 0.004 0.004 17.09 8.0.21 0.006 0.003 17.16 8.0.20 0.007 0.000 17.11 8.0.19 0.004 0.004 17.15 8.0.18 0.003 0.006 17.12 8.0.17 0.004 0.004 17.11 8.0.16 0.000 0.008 17.21 8.0.15 0.008 0.000 17.12 8.0.14 0.003 0.006 17.01 8.0.13 0.007 0.000 13.64 8.0.12 0.004 0.004 17.21 8.0.11 0.003 0.005 17.20 8.0.10 0.004 0.004 17.22 8.0.9 0.004 0.004 17.05 8.0.8 0.007 0.010 17.14 8.0.7 0.000 0.008 17.09 8.0.6 0.000 0.008 17.20 8.0.5 0.000 0.008 17.19 8.0.3 0.014 0.009 17.40 8.0.2 0.013 0.006 17.48 8.0.1 0.005 0.003 17.34 8.0.0 0.012 0.010 17.25 7.4.33 0.003 0.003 16.66 7.4.32 0.000 0.006 16.82 7.4.30 0.007 0.000 16.74 7.4.29 0.000 0.007 16.84 7.4.28 0.003 0.003 16.73 7.4.27 0.004 0.004 16.86 7.4.26 0.000 0.008 16.73 7.4.25 0.000 0.008 16.70 7.4.24 0.002 0.006 16.74 7.4.23 0.004 0.004 16.92 7.4.22 0.006 0.012 16.74 7.4.21 0.010 0.006 16.93 7.4.20 0.003 0.005 16.56 7.4.16 0.008 0.008 16.72 7.4.15 0.006 0.012 17.40 7.4.14 0.006 0.013 17.86 7.4.13 0.009 0.010 16.75 7.4.12 0.010 0.009 16.83 7.4.11 0.006 0.014 16.80 7.4.10 0.014 0.010 16.71 7.4.9 0.007 0.011 16.83 7.4.8 0.015 0.009 19.39 7.4.7 0.017 0.003 16.71 7.4.6 0.011 0.006 16.72 7.4.5 0.004 0.011 16.82 7.4.4 0.003 0.015 16.43 7.4.3 0.014 0.004 16.74 7.4.0 0.009 0.008 15.19 7.3.33 0.000 0.005 13.46 7.3.32 0.005 0.000 13.49 7.3.31 0.004 0.004 16.49 7.3.30 0.007 0.000 16.52 7.3.29 0.011 0.006 16.66 7.3.28 0.009 0.012 16.64 7.3.27 0.007 0.011 17.40 7.3.26 0.007 0.011 16.80 7.3.25 0.013 0.007 16.72 7.3.24 0.009 0.010 16.62 7.3.23 0.009 0.009 16.72 7.3.21 0.007 0.011 16.91 7.3.20 0.013 0.011 16.71 7.3.19 0.007 0.014 16.71 7.3.18 0.006 0.017 16.56 7.3.17 0.010 0.007 16.72 7.3.16 0.009 0.009 16.73 7.3.12 0.007 0.013 15.02 7.3.11 0.003 0.016 14.98 7.3.10 0.000 0.013 14.78 7.3.9 0.010 0.007 14.82 7.3.8 0.000 0.012 15.00 7.3.7 0.000 0.011 15.23 7.3.6 0.006 0.003 15.07 7.3.5 0.006 0.006 14.90 7.3.4 0.007 0.003 14.90 7.3.3 0.005 0.005 15.14 7.3.2 0.006 0.009 16.86 7.3.1 0.000 0.013 16.45 7.3.0 0.006 0.009 16.84 7.2.33 0.006 0.020 16.89 7.2.32 0.014 0.010 16.59 7.2.31 0.000 0.018 16.90 7.2.30 0.009 0.012 16.82 7.2.29 0.010 0.007 16.89 7.2.25 0.004 0.019 15.04 7.2.24 0.006 0.015 15.14 7.2.23 0.007 0.010 15.33 7.2.22 0.000 0.010 15.08 7.2.21 0.000 0.014 14.87 7.2.20 0.007 0.007 15.36 7.2.19 0.003 0.010 15.15 7.2.18 0.010 0.003 15.23 7.2.17 0.007 0.007 14.86 7.2.6 0.009 0.006 16.88 7.2.0 0.004 0.007 19.48 7.1.33 0.003 0.012 15.93 7.1.32 0.007 0.000 15.97 7.1.31 0.007 0.003 15.97 7.1.30 0.005 0.003 15.63 7.1.29 0.004 0.007 15.87 7.1.28 0.000 0.008 15.75 7.1.27 0.007 0.007 15.54 7.1.26 0.003 0.012 15.81 7.1.20 0.005 0.005 15.79 7.1.10 0.006 0.006 17.76 7.1.7 0.000 0.009 17.35 7.1.6 0.010 0.014 19.52 7.1.5 0.006 0.008 17.01 7.1.0 0.003 0.077 22.54 7.0.20 0.000 0.008 16.84 7.0.10 0.000 0.043 20.15 7.0.9 0.013 0.033 20.13 7.0.8 0.013 0.050 20.20 7.0.7 0.017 0.067 20.16 7.0.6 0.007 0.040 20.16 7.0.5 0.003 0.080 20.48 7.0.4 0.013 0.070 20.15 7.0.3 0.013 0.073 20.05 7.0.2 0.010 0.080 20.10 7.0.1 0.003 0.087 20.03 7.0.0 0.013 0.073 20.03 5.6.28 0.003 0.070 21.04 5.6.25 0.007 0.037 20.71 5.6.24 0.017 0.030 20.84 5.6.23 0.003 0.043 20.80 5.6.22 0.010 0.060 20.70 5.6.21 0.003 0.050 20.68 5.6.20 0.003 0.083 21.23 5.6.19 0.007 0.077 21.13 5.6.18 0.003 0.070 21.15 5.6.17 0.013 0.077 21.13 5.6.16 0.007 0.087 21.13 5.6.15 0.000 0.083 21.29 5.6.14 0.003 0.090 21.12 5.6.13 0.013 0.080 21.16 5.6.12 0.010 0.080 21.22 5.6.11 0.020 0.070 21.07 5.6.10 0.020 0.077 21.14 5.6.9 0.000 0.090 21.05 5.6.8 0.003 0.083 20.61 5.6.7 0.003 0.083 20.67 5.6.6 0.013 0.073 20.43 5.6.5 0.010 0.047 20.45 5.6.4 0.013 0.073 20.41 5.6.3 0.007 0.070 20.52 5.6.2 0.013 0.073 20.46 5.6.1 0.013 0.080 20.53 5.6.0 0.003 0.077 20.57 5.5.38 0.000 0.050 20.64 5.5.37 0.000 0.047 20.47 5.5.36 0.010 0.077 20.45 5.5.35 0.003 0.083 20.59 5.5.34 0.013 0.070 21.01 5.5.33 0.003 0.087 20.92 5.5.32 0.017 0.080 20.96 5.5.31 0.013 0.070 20.96 5.5.30 0.007 0.083 21.01 5.5.29 0.017 0.073 20.95 5.5.28 0.020 0.040 20.98 5.5.27 0.013 0.080 20.98 5.5.26 0.007 0.087 21.04 5.5.25 0.003 0.067 20.82 5.5.24 0.020 0.067 20.42 5.5.23 0.000 0.087 20.38 5.5.22 0.017 0.063 20.42 5.5.21 0.007 0.080 20.37 5.5.20 0.003 0.083 20.23 5.5.19 0.000 0.090 20.27 5.5.18 0.020 0.067 20.27 5.5.16 0.007 0.080 20.33 5.5.15 0.007 0.043 20.22 5.5.14 0.000 0.083 20.35 5.5.13 0.007 0.047 20.20 5.5.12 0.010 0.077 20.22 5.5.11 0.010 0.070 20.39 5.5.10 0.007 0.080 20.19 5.5.9 0.007 0.077 20.19 5.5.8 0.013 0.070 20.16 5.5.7 0.007 0.080 20.08 5.5.6 0.007 0.083 20.23 5.5.5 0.010 0.077 20.25 5.5.4 0.003 0.050 20.17 5.5.3 0.010 0.063 20.11 5.5.2 0.010 0.070 20.18 5.5.1 0.003 0.083 20.24 5.5.0 0.010 0.080 20.08
preferences:dark mode live preview
58.61 ms | 401 KiB | 5 Q