phpanimationtimercountdownanimated-gif

How is this animated PNG image aware of the current time and date?


I received an email from a company which has a countdown like this in it:

(This is not the "live" one, it's a copy - as a GIF, not PNG - of how it looked at one point, since the countdown has now ended and no longer displays on the original image's URL).

I viewed the HTML source of the email and it is simply an image file, as below:

<img src="https://www.example.com/f70f250cd4f777ac.png">

As far as I was aware before now, only GIF files could be animated, not PNG files - but I see from searching online that this is apparently called an APNG file.

I am aware of libraries like which you can make images in on-the-fly by writing code in etc, but the page isn't reloading when you open that image's link and from experience of using GD + PHP a while ago, you can't write to the image again once headers have been sent to the browser. Even when you refresh the page, the animation resumes at the same point in the countdown image above.

What technique have they used to create this countdown? / How could I make a countdown image to be sent in an email?


Solution

  • Here's a quick and dirty example I made, which outputs a "live clock" for 120 seconds (and then stops, but it could be made to loop instead - refresh to see it animate if it's stopped):

    This could easily be adapted to be a countdown instead. For sites with a lot of traffic it could be adapted to generate/precache all of the images required for a campaign of a few days ahead of time, and then have the script simply output the precached image for the current date & time.

    Here's the code:

    /sandbox/gif_time.php

    <?php
    
        // Config
        date_default_timezone_set('Europe/London');
        $duration = 120; // seconds
    
        // Vars
        $time = new DateTime();
        $gif = new Imagick();
        $gif->setFormat('gif');
    
        // Loop
        for($i = 0; $i < $duration; $i++) {
            
            // Vars
            $time->add(DateInterval::createFromDateString('1 second'));
            $formatted = $time->format('Y-m-d H:i:s');
            $img = imagecreatetruecolor(200, 50);
            $frames[$i] = new Imagick();
    
            // Background
            $bgCol = imagecolorallocate($img, 255, 255, 255);
            imagefilledrectangle($img, 0, 0, 200, 50, $bgCol);
    
            // Foreground text (can be improved using a TTF font)
            $fgCol = imagecolorallocate($img, 0, 0, 0);
            imagestring($img, 5, 10, 15, $formatted, $fgCol);
            
            // Buffer the image
            ob_start();
            imagegif($img);
            $data = ob_get_contents();
            
            // Clear the buffer & free memory
            ob_end_clean();
            imagedestroy($img);
            
            // Add the image as a frame
            $frames[$i]->readImageBlob($data);
            $frames[$i]->setImageDelay(100); // NOT ms, drop a 0!  100 = 1000ms
            $gif->addImage($frames[$i]);
        }
    
        // Output
        header('Content-Type: image/gif');
        echo $gif->getImagesBlob();
    
        // Free memory
        for($i = 0; $i < $duration; $i++) {
            imagedestroy($frames[$i]);
        }
    
    ?>
    

    /.htaccess

    AddType application/x-httpd-php .gif
    RewriteEngine On
    RewriteBase /
    RewriteRule ^sandbox/time.gif$ sandbox/gif_time.php [L]
    

    It is then accessed via the url /sandbox/time.gif