diff --git a/GIFEncoder.class.php b/GIFEncoder.class.php index 46e5d28..63b5d46 100644 --- a/GIFEncoder.class.php +++ b/GIFEncoder.class.php @@ -31,252 +31,251 @@ class AnimatedGif { -/** - * The built gif image - * @var resource - */ - private $image = ''; + /** + * The built gif image + * @var resource + */ + private $image = ''; -/** - * The array of images to stack - * @var array - */ - private $buffer = array(); + /** + * The array of images to stack + * @var array + */ + private $buffer = array(); -/** - * How many times to loop? 0 = infinite - * @var int - */ - private $number_of_loops = 0; + /** + * How many times to loop? 0 = infinite + * @var int + */ + private $number_of_loops = 0; -/** - * - * @var int - */ - private $DIS = 2; + /** + * + * @var int + */ + private $DIS = 2; -/** - * Which colour is transparent - * @var int - */ - private $transparent_colour = -1; + /** + * Which colour is transparent + * @var int + */ + private $transparent_colour = -1; -/** - * Is this the first frame - * @var int - */ - private $first_frame = true; + /** + * Is this the first frame + * @var int + */ + private $first_frame = true; -/** - * Encode an animated gif - * @param array $source_images An array of binary source images - * @param array $image_delays The delays associated with the source images - * @param type $number_of_loops The number of times to loop - * @param int $transparent_colour_red - * @param int $transparent_colour_green - * @param int $transparent_colour_blue - */ - public function __construct(array $source_images, array $image_delays, $number_of_loops, $transparent_colour_red = -1, $transparent_colour_green = -1, $transparent_colour_blue = -1) - { -/** - * I have no idea what these even do, they appear to do nothing to the image so far - */ - $transparent_colour_red = 0; - $transparent_colour_green = 0; - $transparent_colour_blue = 0; + /** + * Encode an animated gif + * @param array $source_images An array of binary source images + * @param array $image_delays The delays associated with the source images + * @param type $number_of_loops The number of times to loop + * @param int $transparent_colour_red + * @param int $transparent_colour_green + * @param int $transparent_colour_blue + */ + public function __construct(array $source_images, array $image_delays, $number_of_loops, $transparent_colour_red = -1, $transparent_colour_green = -1, $transparent_colour_blue = -1) + { + /** + * I have no idea what these even do, they appear to do nothing to the image so far + */ + $transparent_colour_red = 0; + $transparent_colour_green = 0; + $transparent_colour_blue = 0; - $this->number_of_loops = ($number_of_loops > -1) ? $number_of_loops : 0; - $this->set_transparent_colour($transparent_colour_red, $transparent_colour_green, $transparent_colour_blue); - $this->buffer_images($source_images); + $this->number_of_loops = ($number_of_loops > -1) ? $number_of_loops : 0; + $this->set_transparent_colour($transparent_colour_red, $transparent_colour_green, $transparent_colour_blue); + $this->buffer_images($source_images); - $this->addHeader(); - for ($i = 0; $i < count($this->buffer); $i++) { - $this->addFrame($i, $image_delays[$i]); + $this->addHeader(); + for ($i = 0; $i < count($this->buffer); $i++) { + $this->addFrame($i, $image_delays[$i]); + } + } + /** + * Set the transparent colour + * @param int $red + * @param int $green + * @param int $blue + */ + private function set_transparent_colour($red, $green, $blue) + { + $this->transparent_colour = ($red > -1 && $green > -1 && $blue > -1) ? + ($red | ($green << 8) | ($blue << 16)) : -1; } - } -/** - * Set the transparent colour - * @param int $red - * @param int $green - * @param int $blue - */ - private function set_transparent_colour($red, $green, $blue) - { - $this->transparent_colour = ($red > -1 && $green > -1 && $blue > -1) ? - ($red | ($green << 8) | ($blue << 16)) : -1; - } -/** - * Buffer the images and check to make sure they are vaild - * @param array $source_images the array of source images - * @throws Exception - */ - private function buffer_images($source_images) - { - for ($i = 0; $i < count($source_images); $i++) { - $this->buffer[] = $source_images[$i]; - if (substr($this->buffer[$i], 0, 6) != "GIF87a" && substr($this->buffer[$i], 0, 6) != "GIF89a") { - throw new Exception('Image at position ' . $i . ' is not a gif'); - } - for ($j = (13 + 3 * (2 << (ord($this->buffer[$i]{10}) & 0x07))), $k = true; $k; $j++) { - switch ($this->buffer[$i]{ $j}) { - case "!": - if ((substr($this->buffer[$i], ($j + 3), 8)) == "NETSCAPE") { - throw new Exception('You cannot make an animation from an animated gif.'); - } - break; - case ";": - $k = false; - break; + /** + * Buffer the images and check to make sure they are vaild + * @param array $source_images the array of source images + * @throws Exception + */ + private function buffer_images($source_images) + { + for ($i = 0; $i < count($source_images); $i++) { + $this->buffer[] = $source_images[$i]; + if (substr($this->buffer[$i], 0, 6) != "GIF87a" && substr($this->buffer[$i], 0, 6) != "GIF89a") { + throw new Exception('Image at position ' . $i . ' is not a gif'); + } + for ($j = (13 + 3 * (2 << (ord($this->buffer[$i]{10}) & 0x07))), $k = true; $k; $j++) { + switch ($this->buffer[$i]{ $j}) { + case "!": + if ((substr($this->buffer[$i], ($j + 3), 8)) == "NETSCAPE") { + throw new Exception('You cannot make an animation from an animated gif.'); + } + break; + case ";": + $k = false; + break; + } + } } - } } - } -/** - * Add the gif header to the image - */ - private function addHeader() - { - $cmap = 0; - $this->image = 'GIF89a'; - if (ord($this->buffer[0]{10}) & 0x80) { - $cmap = 3 * (2 << (ord($this->buffer[0]{10}) & 0x07)); - $this->image .= substr($this->buffer[0], 6, 7); - $this->image .= substr($this->buffer[0], 13, $cmap); - $this->image .= "!\377\13NETSCAPE2.0\3\1" . $this->word($this->number_of_loops) . "\0"; + /** + * Add the gif header to the image + */ + private function addHeader() + { + $cmap = 0; + $this->image = 'GIF89a'; + if (ord($this->buffer[0]{10}) & 0x80) { + $cmap = 3 * (2 << (ord($this->buffer[0]{10}) & 0x07)); + $this->image .= substr($this->buffer[0], 6, 7); + $this->image .= substr($this->buffer[0], 13, $cmap); + $this->image .= "!\377\13NETSCAPE2.0\3\1" . $this->word($this->number_of_loops) . "\0"; + } } - } -/** - * Add a frame to the animation - * @param int $frame The frame to be added - * @param int $delay The delay associated with the frame - */ - private function addFrame($frame, $delay) - { - $Locals_str = 13 + 3 * (2 << (ord($this->buffer[$frame]{10}) & 0x07)); + /** + * Add a frame to the animation + * @param int $frame The frame to be added + * @param int $delay The delay associated with the frame + */ + private function addFrame($frame, $delay) + { + $Locals_str = 13 + 3 * (2 << (ord($this->buffer[$frame]{10}) & 0x07)); - $Locals_end = strlen($this->buffer[$frame]) - $Locals_str - 1; - $Locals_tmp = substr($this->buffer[$frame], $Locals_str, $Locals_end); + $Locals_end = strlen($this->buffer[$frame]) - $Locals_str - 1; + $Locals_tmp = substr($this->buffer[$frame], $Locals_str, $Locals_end); - $Global_len = 2 << (ord($this->buffer[0]{10}) & 0x07); - $Locals_len = 2 << (ord($this->buffer[$frame]{10}) & 0x07); + $Global_len = 2 << (ord($this->buffer[0]{10}) & 0x07); + $Locals_len = 2 << (ord($this->buffer[$frame]{10}) & 0x07); - $Global_rgb = substr($this->buffer[0], 13, 3 * (2 << (ord($this->buffer[0]{10}) & 0x07))); - $Locals_rgb = substr($this->buffer[$frame], 13, 3 * (2 << (ord($this->buffer[$frame]{10}) & 0x07))); + $Global_rgb = substr($this->buffer[0], 13, 3 * (2 << (ord($this->buffer[0]{10}) & 0x07))); + $Locals_rgb = substr($this->buffer[$frame], 13, 3 * (2 << (ord($this->buffer[$frame]{10}) & 0x07))); - $Locals_ext = "!\xF9\x04" . chr(($this->DIS << 2) + 0) . - chr(($delay >> 0) & 0xFF) . chr(($delay >> 8) & 0xFF) . "\x0\x0"; + $Locals_ext = "!\xF9\x04" . chr(($this->DIS << 2) + 0) . + chr(($delay >> 0) & 0xFF) . chr(($delay >> 8) & 0xFF) . "\x0\x0"; - if ($this->transparent_colour > -1 && ord($this->buffer[$frame]{10}) & 0x80) { - for ($j = 0; $j < (2 << (ord($this->buffer[$frame]{10}) & 0x07)); $j++) { - if ( - ord($Locals_rgb{3 * $j + 0}) == (($this->transparent_colour >> 16) & 0xFF) && - ord($Locals_rgb{3 * $j + 1}) == (($this->transparent_colour >> 8) & 0xFF) && - ord($Locals_rgb{3 * $j + 2}) == (($this->transparent_colour >> 0) & 0xFF) - ) { - $Locals_ext = "!\xF9\x04" . chr(($this->DIS << 2) + 1) . - chr(($delay >> 0) & 0xFF) . chr(($delay >> 8) & 0xFF) . chr($j) . "\x0"; - break; + if ($this->transparent_colour > -1 && ord($this->buffer[$frame]{10}) & 0x80) { + for ($j = 0; $j < (2 << (ord($this->buffer[$frame]{10}) & 0x07)); $j++) { + if ( + ord($Locals_rgb{3 * $j + 0}) == (($this->transparent_colour >> 16) & 0xFF) && + ord($Locals_rgb{3 * $j + 1}) == (($this->transparent_colour >> 8) & 0xFF) && + ord($Locals_rgb{3 * $j + 2}) == (($this->transparent_colour >> 0) & 0xFF) + ) { + $Locals_ext = "!\xF9\x04" . chr(($this->DIS << 2) + 1) . + chr(($delay >> 0) & 0xFF) . chr(($delay >> 8) & 0xFF) . chr($j) . "\x0"; + break; + } + } } - } - } - switch ($Locals_tmp{0}) { - case "!": - $Locals_img = substr($Locals_tmp, 8, 10); - $Locals_tmp = substr($Locals_tmp, 18, strlen($Locals_tmp) - 18); - break; - case ",": - $Locals_img = substr($Locals_tmp, 0, 10); - $Locals_tmp = substr($Locals_tmp, 10, strlen($Locals_tmp) - 10); - break; - } - if (ord($this->buffer[$frame]{10}) & 0x80 && $this->first_frame === false) { - if ($Global_len == $Locals_len) { - if ($this->blockCompare($Global_rgb, $Locals_rgb, $Global_len)) { - $this->image .= ($Locals_ext . $Locals_img . $Locals_tmp); + switch ($Locals_tmp{0}) { + case "!": + $Locals_img = substr($Locals_tmp, 8, 10); + $Locals_tmp = substr($Locals_tmp, 18, strlen($Locals_tmp) - 18); + break; + case ",": + $Locals_img = substr($Locals_tmp, 0, 10); + $Locals_tmp = substr($Locals_tmp, 10, strlen($Locals_tmp) - 10); + break; + } + if (ord($this->buffer[$frame]{10}) & 0x80 && $this->first_frame === false) { + if ($Global_len == $Locals_len) { + if ($this->blockCompare($Global_rgb, $Locals_rgb, $Global_len)) { + $this->image .= ($Locals_ext . $Locals_img . $Locals_tmp); + } else { + $byte = ord($Locals_img{9}); + $byte |= 0x80; + $byte &= 0xF8; + $byte |= (ord($this->buffer[0]{10}) & 0x07); + $Locals_img{9} = chr($byte); + $this->image .= ($Locals_ext . $Locals_img . $Locals_rgb . $Locals_tmp); + } + } else { + $byte = ord($Locals_img{9}); + $byte |= 0x80; + $byte &= 0xF8; + $byte |= (ord($this->buffer[$frame]{10}) & 0x07); + $Locals_img{9} = chr($byte); + $this->image .= ($Locals_ext . $Locals_img . $Locals_rgb . $Locals_tmp); + } } else { - $byte = ord($Locals_img{9}); - $byte |= 0x80; - $byte &= 0xF8; - $byte |= (ord($this->buffer[0]{10}) & 0x07); - $Locals_img{9} = chr($byte); - $this->image .= ($Locals_ext . $Locals_img . $Locals_rgb . $Locals_tmp); + $this->image .= ($Locals_ext . $Locals_img . $Locals_tmp); } - } else { - $byte = ord($Locals_img{9}); - $byte |= 0x80; - $byte &= 0xF8; - $byte |= (ord($this->buffer[$frame]{10}) & 0x07); - $Locals_img{9} = chr($byte); - $this->image .= ($Locals_ext . $Locals_img . $Locals_rgb . $Locals_tmp); - } - } else { - $this->image .= ($Locals_ext . $Locals_img . $Locals_tmp); + $this->first_frame = false; } - $this->first_frame = false; - } - -/** - * Add the gif footer - */ - private function addFooter() - { - $this->image .= ";"; - } -/** - * Compare gif blocks? What is a block? - * @param type $GlobalBlock - * @param type $LocalBlock - * @param type $Len - * @return type - */ - private function blockCompare($GlobalBlock, $LocalBlock, $Len) - { - for ($i = 0; $i < $Len; $i++) { - if ( - $GlobalBlock{3 * $i + 0} != $LocalBlock{3 * $i + 0} || - $GlobalBlock{3 * $i + 1} != $LocalBlock{3 * $i + 1} || - $GlobalBlock{3 * $i + 2} != $LocalBlock{3 * $i + 2} - ) { - return (0); - } + /** + * Add the gif footer + */ + private function addFooter() + { + $this->image .= ";"; } - return (1); - } + /** + * Compare gif blocks? What is a block? + * @param type $GlobalBlock + * @param type $LocalBlock + * @param type $Len + * @return type + */ + private function blockCompare($GlobalBlock, $LocalBlock, $Len) + { + for ($i = 0; $i < $Len; $i++) { + if ( + $GlobalBlock{3 * $i + 0} != $LocalBlock{3 * $i + 0} || + $GlobalBlock{3 * $i + 1} != $LocalBlock{3 * $i + 1} || + $GlobalBlock{3 * $i + 2} != $LocalBlock{3 * $i + 2} + ) { + return (0); + } + } -/** - * No clue - * @param int $int - * @return string the char you meant? - */ - private function word($int) - { - return (chr($int & 0xFF) . chr(($int >> 8) & 0xFF)); - } + return (1); + } -/** - * Return the animated gif - * @return type - */ - public function getAnimation() - { - return $this->image; - } + /** + * No clue + * @param int $int + * @return string the char you meant? + */ + private function word($int) + { + return (chr($int & 0xFF) . chr(($int >> 8) & 0xFF)); + } -/** - * Return the animated gif - * @return type - */ - public function display() - { -//late footer add - $this->addFooter(); - header('Content-type:image/jpg'); - echo $this->image; - } + /** + * Return the animated gif + * @return type + */ + public function getAnimation() + { + return $this->image; + } + /** + * Return the animated gif + * @return type + */ + public function display() + { + //late footer add + $this->addFooter(); + header('Content-type:image/jpg'); + echo $this->image; + } } diff --git a/README.md b/README.md index 3917fde..6c3249d 100644 --- a/README.md +++ b/README.md @@ -29,3 +29,7 @@ An example of this would be `http://[server-address]/countdown.php?time=2016-12- ### Fonts Any font file can be used as the base font for the countdowm timer. To use a custom font you'll need to upload it to the `fonts` directory and reference the exact name in the query string parameter `font`. *Note: fonts must be uploaded using the `ttf` file extension*. + +### Preview + +[![image](countdown.jpg)](https://hizliresim.com/grpPNR) \ No newline at end of file diff --git a/countdown.jpg b/countdown.jpg new file mode 100644 index 0000000..6aa209b Binary files /dev/null and b/countdown.jpg differ diff --git a/countdown.php b/countdown.php index 2d84468..d05850c 100644 --- a/countdown.php +++ b/countdown.php @@ -7,280 +7,276 @@ */ class CountdownTimer { - - /** - * @var object - */ - private $base; - - /** - * @var object - */ - private $box; - - /** - * @var int - */ - private $width = 0; - - /** - * @var int - */ - private $height = 0; - - /** - * @var int - */ - private $xOffset = 0; - - /** - * @var int - */ - private $yOffset = 0; - - /** - * @var int - */ - private $delay = 100; - - /** - * @var array - */ - private $frames = array(); - - /** - * @var array - */ - private $delays = array(); - - /** - * @var array - */ - private $date = array(); - - /** - * @var array - */ - private $fontSettings = array(); - - /** - * @var array - */ - private $boundingBox = array(); - - /** - * @var string - */ - private $fontPath = 'fonts/'; - - /** - * @var int - */ - private $seconds = 30; - - /** - * hex2rgb - * Convert a hex - * colour to rgb - * @param string $hex - * @return array - */ - private function hex2rgb($hex) - { - $hex = str_replace('#', '', $hex); - - 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)); - } - $rgb = array($r, $g, $b); - - return $rgb; - } - - /** - * createFilledBox - * Create a filled box - * to use at the base - * @param $image - */ - private function createFilledBox($image) - { - imagefilledrectangle( - $image, - 0, - 0, - $this->width, - $this->height, - imagecolorallocate( - $image, - $this->boxColor[0], - $this->boxColor[1], - $this->boxColor[2] - ) - ); - } - - /** - * CountdownTimer constructor. - * - * @param $settings - */ - public function __construct($settings) - { - $this->width = $settings['width']; - $this->height = $settings['height']; - $this->boxColor = $settings['boxColor']; - $this->xOffset = $settings['xOffset']; - $this->yOffset = $settings['yOffset']; - $this->boxColor = $this->hex2rgb($settings['boxColor']); - $this->fontColor = $this->hex2rgb($settings['fontColor']); - - $this->labelOffsets = explode(',', $settings['labelOffsets']); - - $this->date['time'] = $settings['time']; - $this->date['futureDate'] = new DateTime(date('r', strtotime($settings['time']))); - $this->date['timeNow'] = time(); - $this->date['now'] = new DateTime(date('r', time())); - - // create new images - $this->box = imagecreatetruecolor($this->width, $this->height); - $this->base = imagecreatetruecolor($this->width, $this->height); - - $this->fontSettings['path'] = $this->fontPath . $settings['font'] . '.ttf'; - $this->fontSettings['color'] = imagecolorallocate($this->box, $this->fontColor[0], $this->fontColor[1], $this->fontColor[2]); - $this->fontSettings['size'] = $settings['fontSize']; - $this->fontSettings['characterWidth'] = imagefontwidth($this->fontSettings['path']); - - // get the width of each character - $string = "0:"; - $size = $this->fontSettings['size']; - $angle = 0; - $fontfile = $this->fontSettings['path']; - - $strlen = strlen($string); - for ($i = 0; $i < $strlen; $i++) { - $dimensions = imagettfbbox($size, $angle, $fontfile, $string[$i]); - $this->fontSettings['characterWidths'][] = array( - $string[i] => $dimensions[2] - ); + /** + * @var object + */ + private $base; + + /** + * @var object + */ + private $box; + + /** + * @var int + */ + private $width = 0; + + /** + * @var int + */ + private $height = 0; + + /** + * @var int + */ + private $xOffset = 0; + + /** + * @var int + */ + private $yOffset = 0; + + /** + * @var int + */ + private $delay = 100; + + /** + * @var array + */ + private $frames = array(); + + /** + * @var array + */ + private $delays = array(); + + /** + * @var array + */ + private $date = array(); + + /** + * @var array + */ + private $fontSettings = array(); + + /** + * @var array + */ + private $boundingBox = array(); + + /** + * @var string + */ + private $fontPath = 'fonts/'; + + /** + * @var int + */ + private $seconds = 60; + + /** + * CountdownTimer constructor. + * + * @param $settings + */ + public function __construct($settings) + { + $this->width = $settings['width']; + $this->height = $settings['height']; + $this->boxColor = $settings['boxColor']; + $this->xOffset = $settings['xOffset']; + $this->yOffset = $settings['yOffset']; + $this->boxColor = $this->hex2rgba($settings['boxColor'], false, '#4dd1f2'); + $this->fontColor = $this->hex2rgba($settings['fontColor'], false, '#2175ba'); + + $this->labelOffsets = explode(',', $settings['labelOffsets']); + + $this->date['time'] = $settings['time']; + $this->date['futureDate'] = new DateTime(date('r', strtotime($settings['time']))); + $this->date['timeNow'] = time(); + $this->date['now'] = new DateTime(date('r', time())); + + // create new images + $this->box = imagecreatetruecolor($this->width, $this->height); + $this->base = imagecreatetruecolor($this->width, $this->height); + + $this->fontSettings['path'] = realpath($this->fontPath . $settings['font'] . '.ttf'); + $this->fontSettings['color'] = imagecolorallocate($this->box, $this->fontColor[0], $this->fontColor[1], $this->fontColor[2]); + $this->fontSettings['size'] = $settings['fontSize']; + $this->fontSettings['characterWidth'] = imagefontwidth($this->fontSettings['size']); + + // get the width of each character + $string = "0:"; + $size = $this->fontSettings['size']; + $angle = 0; + $fontfile = $this->fontSettings['path']; + + $strlen = strlen($string); + for ($i = 0; $i < $strlen; $i++) { + $dimensions = imagettfbbox($size, $angle, $fontfile, $string[$i]); + $this->fontSettings['characterWidths'][] = array( + $string[$i] => $dimensions[2], + ); + } + + $this->images = array( + 'box' => $this->box, + 'base' => $this->base, + ); + + // create empty filled rectangles + foreach ($this->images as $image) { + $this->createFilledBox($image); + } + + $this->createFrames(); } - $this->images = array( - 'box' => $this->box, - 'base' => $this->base, - ); - - // create empty filled rectangles - foreach ($this->images as $image) { - $this->createFilledBox($image); + /** + * Hex to RGBa + * + * @param string $color: hex color + * @param bool|float $opacity: alpha channel, optional + * @param string $default: default return value + * @source: https://gist.github.com/EgoistDeveloper/42c36b1389cffb1bf613f6f6ebefa47b + * @return array|string + */ + function hex2rgba($color, $opacity = false, $default = '#758491') + { + preg_match('/#?([a-fA-F-0-9]{3,8})/', $color, $match); + + if ($match){ + preg_match_all('/#?([a-fA-F-0-9]{1,2})([a-fA-F-0-9]{1,2})([a-fA-F-0-9]{1,2})/', $color, $matches); + + if ($matches){ + unset($matches[0]); + + foreach ($matches as $key => $value) { + $matches[$key] = $value[0]; + } + + // reorder array and hexadec to rgb + return array_map('hexdec', array_values($matches)); + } + } + + return $this->hex2rgba($default); } - $this->createFrames(); - } - - /** - * createFrames - * Create all of the frames for - * the countdown timer - * @return void - */ - public function createFrames() - { - $this->boundingBox = imagettfbbox($this->fontSettings['size'], 0, $this->fontSettings['path'], '00:00:00:00'); - $this->characterDimensions = imagettfbbox($this->fontSettings['size'], 0, $this->fontSettings['path'], '0'); - $this->characterWidth = $this->characterDimensions[2]; - $this->characterHeight = abs($this->characterDimensions[1] + $this->characterDimensions[7]); - - $this->base = $this->applyTextToImage($this->base, $this->fontSettings, $this->date); - - // create each frame - for ($i = 0; $i <= $this->seconds; $i++) { - $layer = imagecreatetruecolor($this->width, $this->height); - $this->createFilledBox($layer); - - $layer = $this->applyTextToImage($layer, $this->fontSettings, $this->date); + /** + * createFilledBox + * Create a filled box + * to use at the base + * @param $image + */ + private function createFilledBox($image) + { + imagefilledrectangle($image, 0, 0, $this->width, $this->height, imagecolorallocate($image, $this->boxColor[0], $this->boxColor[1], $this->boxColor[2]) + ); } - $this->showImage(); - } - - /** - * applyTextToImage - * Apply each time stamp - * to the image - * @param $image - * @param $font - * @param $date - * @return mixed - */ - private function applyTextToImage($image, $font, $date) - { - $interval = date_diff( - $date['futureDate'], - $date['now'] - ); - - if ($date['futureDate'] < $date['now']) { - $text = $interval->format('00:00:00:00'); - $this->loops = 1; - } else { - $text = $interval->format('0%a:%H:%I:%S'); - $this->loops = 0; + /** + * createFrames + * Create all of the frames for + * the countdown timer + * @return void + */ + public function createFrames() + { + $this->boundingBox = imagettfbbox($this->fontSettings['size'], 0, $this->fontSettings['path'], '00:00:00:00'); + $this->characterDimensions = imagettfbbox($this->fontSettings['size'], 0, $this->fontSettings['path'], '0'); + $this->characterWidth = $this->characterDimensions[2]; + $this->characterHeight = abs($this->characterDimensions[1] + $this->characterDimensions[7]); + + $this->base = $this->applyTextToImage($this->base, $this->fontSettings, $this->date); + + // create each frame + for ($i = 0; $i <= $this->seconds; $i++) { + $layer = imagecreatetruecolor($this->width, $this->height); + $this->createFilledBox($layer); + + $layer = $this->applyTextToImage($layer, $this->fontSettings, $this->date); + } + + $this->showImage(); } - $labels = array('Days', 'Hrs', 'Mins', 'Secs'); - - // apply the labels to the image $this->yOffset + ($this->characterHeight * 0.8) - foreach ($labels as $key => $label) { - imagettftext($image, 15, 0, $this->xOffset + ($this->characterWidth * $this->labelOffsets[$key]), 98, $font['color'], $font['path'], $label); + /** + * applyTextToImage + * Apply each time stamp + * to the image + * @param $image + * @param $font + * @param $date + * @return mixed + */ + private function applyTextToImage($image, $font, $date) + { + $interval = date_diff( + $date['futureDate'], + $date['now'] + ); + + if ($date['futureDate'] < $date['now']) { + $text = $interval->format('00:00:00:00'); + $this->loops = 1; + } else { + $text = $interval->format('%a:%H:%I:%S'); + $this->loops = 0; + } + + $labels = array('Days', 'Hrs', 'Mins', 'Secs'); + + // apply the labels to the image $this->yOffset + ($this->characterHeight * 0.8) + foreach ($labels as $key => $label) { + imagettftext($image, 15, 0, $this->xOffset + ($this->characterWidth * $this->labelOffsets[$key]), 98, $font['color'], $font['path'], $label); + } + + // apply time to new image + imagettftext($image, $font['size'], 0, $this->xOffset, $this->yOffset, $font['color'], $font['path'], $text); + + ob_start(); + imagegif($image); + $this->frames[] = ob_get_contents(); + $this->delays[] = $this->delay; + ob_end_clean(); + + $this->date['now']->modify('+1 second'); + + return $image; } - // apply time to new image - imagettftext($image, $font['size'], 0, $this->xOffset, $this->yOffset, $font['color'], $font['path'], $text); - - ob_start(); - imagegif($image); - $this->frames[] = ob_get_contents(); - $this->delays[] = $this->delay; - ob_end_clean(); - - $this->date['now']->modify('+1 second'); - - return $image; - } - - /** - * showImage - * Create the animated gif - * @return void - */ - public function showImage() - { - $gif = new AnimatedGif($this->frames, $this->delays, $this->loops); - $gif->display(); - } + /** + * Create the animated gif + * + * @return void + */ + public function showImage() + { + $gif = new AnimatedGif($this->frames, $this->delays, $this->loops); + $gif->display(); + } } -/** - * Create a new countdown - */ -new CountdownTimer(array( - 'time' => $_GET['time'], - 'width' => isset($_GET['width']) ? $_GET['width'] : 640, - 'height' => isset($_GET['height']) ? $_GET['height'] : 110, - 'boxColor' => isset($_GET['boxColor']) ? $_GET['boxColor'] : '#000', - 'font' => isset($_GET['font']) ? $_GET['font'] : 'BebasNeue', - 'fontColor' => isset($_GET['fontColor']) ? $_GET['fontColor'] : '#fff', - 'fontSize' => isset($_GET['fontSize']) ? $_GET['fontSize'] : 60, - 'xOffset' => isset($_GET['xOffset']) ? $_GET['xOffset'] : 155, - 'yOffset' => isset($_GET['yOffset']) ? $_GET['yOffset'] : 70, - 'labelOffsets' => isset($_GET['labelOffsets']) ? $_GET['labelOffsets'] : "1.4,5,8,11", -)); + +// get options +$options = [ + 'time' => $_GET['time'], + 'width' => isset($_GET['width']) ? $_GET['width'] : 640, + 'height' => isset($_GET['height']) ? $_GET['height'] : 110, + 'boxColor' => isset($_GET['boxColor']) ? $_GET['boxColor'] : '#000', + 'font' => isset($_GET['font']) ? $_GET['font'] : 'BebasNeue', + 'fontColor' => isset($_GET['fontColor']) ? $_GET['fontColor'] : '#fff', + 'fontSize' => isset($_GET['fontSize']) ? $_GET['fontSize'] : 60, + 'xOffset' => isset($_GET['xOffset']) ? $_GET['xOffset'] : 155, + 'yOffset' => isset($_GET['yOffset']) ? $_GET['yOffset'] : 70, + 'labelOffsets' => isset($_GET['labelOffsets']) ? $_GET['labelOffsets'] : "1.4,5,8,11", +]; + +// create a new countdown +new CountdownTimer($options); // http://[server-address]/countdown.php?time=2016-12-25+00:00:01&width=640&height=110&boxColor=8B2860&font=BebasNeue&fontColor=FBB92C&fontSize=60&xOffset=155&yOffset=70&labelOffsets=1.4,5,8,11