
Time.gif - def-
https://hookrace.net/blog/time.gif
======
koliber
In 1994 I was in high school, and there were no animated GIFs. One way you
could make images move in the web browser was to use a mechanism similar to
this.

I wrote a C program which would load 6 frames of a smiley face animation and
would feed them sequentially, in an endless loop, to anyone who requested the
image. Mosaic was happy to animate them.

I get called in to the web mistress's office. The web server is down. We had a
donated Silicon Graphics Origin server, if my memory serves me correctly. This
was a beefy machine.

The cgi-bin C program would load 6 images, as fast as it possibly could, and
dump them into a network socket. It would not throttle. It would not check if
the client disconnected. It had one job. It did it efficiently, and
ruthlessly.

Poor server.

~~~
paulpauper
how can such an old browser run a C program embedded within it? Can someone
elaborate how this could have been done

~~~
MagerValp
NCSA httpd introduced the Common Gateway Interface which allows you to execute
any binary, and whatever it puts on stdout is sent as the reply. Back then it
was typically a Perl script or a compiled C binary.

[https://en.m.wikipedia.org/wiki/Common_Gateway_Interface](https://en.m.wikipedia.org/wiki/Common_Gateway_Interface)

~~~
neuromancer2701
My company makes a DAS(distributed Antenna System) product with an embedded
web interface. All of our web sites have C/C++ cgi back ends. There are more
makefiles in the Web folder than the whole rest of system. It is quite mind
boggling. But the engineer that has control over this area is stuck in the
90s.

~~~
Drdrdrq
My main objection to such systems is security. It is difficult enough to take
care of it in modern frameworks, but in C?

------
janci
I did something similar long time ago with multipart/x-mixed-replace content
type. [http://zabasoft.xf.cz/clock.gif](http://zabasoft.xf.cz/clock.gif)

~~~
dom0
Interesting. Firefox' developer console does not understand this kind of
request properly and shows its termination after the first frame. Chromium on
the other hand handles it correctly.

~~~
TwoBit
Works in Firefox for me.

------
nkkollaw
This is absolutely awesome.

I wonder if this can be used to stream regular GIFs, so that you don't have to
wait for the whole thing to load before seeing the animation.

I'm currently working on a project focusing on GIFs
([https://www.gifsonic.com](https://www.gifsonic.com)), I'll definitely study
this to see if it's possible.

~~~
bentpins
That is how my browser behaves normally in Chrome at least. Progressive
loading of normal .gifs, playing frames as they are available

~~~
nkkollaw
Sure, but the animation sucks. Extremely choppy and slowed down.

I wonder if this technique can optimize preloading.

For instance, we could send out only 1/2 of the frames (of course, with twice
the delay to keep the same animation speed), then load the rest as it's
available.

I have no idea what I'm talking about yet, but there seem to be something
here.

~~~
soneca
I would prefer, as UX, that it would follow this order:

\- First load first frame on lowres (may be so lo that is blurred)

\- Then add a small rotating _loading icon_ on top of image, possibly with a
notation that is a GIF

\- Then load first frame completely at correct resolution

\- Then load all the other frames _in the background_ , only showing me the
first frame still

\- When all frames are completely loaded, remove loading rotating icon and run
the GIF normally.

~~~
nkkollaw
Awesome suggestions. I'll try to see if it's possible.

------
oxymoron
I did the same thing about fifteen years ago by generating a mJPEG stream from
a PHP-script. As far as I can remember, it seemed more reliable than using
GIF. See
[https://en.wikipedia.org/wiki/Motion_JPEG](https://en.wikipedia.org/wiki/Motion_JPEG)

~~~
icebraining
The main advantage is that, because a video format rather than an image that
can loop, the player can discard past frames. The GIF method is probably
constantly leaking memory.

~~~
dom0
> The GIF method is probably constantly leaking memory.

If the browser only keeps compressed frames, 16 GB will last for more than a
year.

------
have_faith
This technique used to be used to embed "videos" into html emails years ago.
Haven't seen it used in a long time maybe email clients block the streaming
behavior now (for good reason).

------
ungzd
Tried to make it output with chunked-encoding:

\- In Chrome it shows nothing (looks like it waits for end of stream)

\- In Safari it shows only the first frame

\- In Firefox it works (shows animated clock)

Branch with chunked encoding: [https://github.com/kolen/time.gif/tree/chunked-
encoding](https://github.com/kolen/time.gif/tree/chunked-encoding)

------
warent
This is really cool! Completely suboptimal but fascinating none the less.
Great project and idea :) would be interested in hearing some people's ideas
for real applications of this

~~~
mxstbr
One use case for automatically adapting/live updating gifs is emails since
HTML in emails can only have a very limited subset of functionality.

One can use automatically generated gifs to add things like countdown timers
based on the opening time of the email. (i.e. loading time of the image) See
for example this post: [https://litmus.com/community/learning/27-how-to-add-a-
countd...](https://litmus.com/community/learning/27-how-to-add-a-countdown-
timer-to-your-email)

~~~
botverse
This won't work with gmail, the images are precached.

~~~
mnutt
Actually, that's not true. GMail proxies images, but doesn't do a lot in the
way of caching. They actually cache the _DOM_ when moving between messages for
a short while, but a browser reload will reset it.

~~~
botverse
Been working for 3 years in the past in an email isp I had different
information, gmail did cache the images and did it "forever". May be this
changed recently?

More info: [https://litmus.com/blog/gmail-adds-image-caching-what-you-
ne...](https://litmus.com/blog/gmail-adds-image-caching-what-you-need-to-know)

------
maweki
So this was done during a programming paradigms course at KIT? I'm teaching
functional programming basics using Haskell at my university. At the end of
the semester we aren't quite that far. But I am far from sure whether this
exercise, just looking at the given types, has didactic value and I wonder how
much of the stuff the instructor has given and how much the students worked
out themselves given the course materials.

I would be a bit hesitant (teaching-wise), to talk about any function of the
type IO () -> IO Char -> (Frame -> IO ()) -> IO ()

Although, not to be a spoil sport, it seems like a fun thing to do over a long
weekend.

~~~
def-
This is just using the framework that I made for the exercise. The students
didn't have to do any Crazy IO stuff. You can see the parts under "Aufgabe"
here, which is what they were supposed to code:
[https://github.com/def-/gifstream/blob/master/SnakeFinished....](https://github.com/def-/gifstream/blob/master/SnakeFinished.hs#L67)

Exercises in German here:
[https://github.com/def-/gifstream/blob/master/Aufgabe.pdf](https://github.com/def-/gifstream/blob/master/Aufgabe.pdf)

~~~
maweki
This seems interesting. Maybe I can use something similar next year to
generate some interest. Without IO (which is monads, which is too advances
since we also do functional C# and functional java paradigms in the same
course) the subject matter is always a bit dry since the students have nothing
but the ghci repl to get any interaction or feedback going.

~~~
wyager
What if you were to give students some functions like

    
    
        imShow :: [[Int]] -> IO ()
        playSound [Int] -> IO ()
    

? This would give them a little more liveliness but wouldn't require them to
understand anything beyond "IO () is something that the repl can run". If
they're feeling exploratory, maybe give them a few monadic combinators like >>
to play around with, possibly specialized to IO.

~~~
WorldMaker
You could also build a "sandbox" monad specifically for the class/framework.
Let the students treat the monad as a blackbox Turing machine/state machine,
unless they get time/interest/show aptitude to dive deeper. Doing that gives
you the benefit that they don't accidentally google "Haskell IO" and fall down
the monad rabbit hole without some preparation.

------
garaetjjte
see also raytracing clock on PNG:
[http://www.ioccc.org/2013/mills/hint.html](http://www.ioccc.org/2013/mills/hint.html)

~~~
TheSpiceIsLife
I know I'm a bit fatigued... but where / how do I download the doflickymabob
to make this go?

~~~
pdkl95
The source (and Makefile which defines the camera/light coord. see hint.html)
for the winning IOCCC entries are available in the parent directory.

[http://www.ioccc.org/2013/mills/](http://www.ioccc.org/2013/mills/)

It might be more convenient to download the annual winning entry tarball.

[http://www.ioccc.org/2013/2013.tar.bz2](http://www.ioccc.org/2013/2013.tar.bz2)

Alternatively, try the index for all of the winning entry files.

[http://www.ioccc.org/years.html](http://www.ioccc.org/years.html)

edit: By the way, if you download 2013.tar.bz2, I highly recommend checking
out the cable3, which implements an entire IBM PC capable of running Windows
3.0 in only 4043 bytes (8086 nibbles).

[http://www.ioccc.org/2013/cable3/hint.html](http://www.ioccc.org/2013/cable3/hint.html)

~~~
0xcde4c3db
> edit: By the way, if you download 2013.tar.bz2, I highly recommend checking
> out the cable3, which implements an entire IBM PC capable of running Windows
> 3.0 in only 4043 bytes (8086 nibbles).

People interested in that emulator may also want to know that the non-
obfuscated version (still only 760 physical lines of C, though that's partly
achieved by putting opcode information in the BIOS ROM) has moved to GitHub:

[https://github.com/adriancable/8086tiny](https://github.com/adriancable/8086tiny)

------
miduil
When you are running out of time, but still got a decent video player ready:

    
    
       $ mpv --cache=no https://hookrace.net/time.gif

------
jbochi
This reminds me of a project I've created a few years ago that does live video
streaming with endless GIFs:
[https://github.com/jbochi/gifstreaming](https://github.com/jbochi/gifstreaming)

------
Jonas_ba
Very interesting from a tech perspective, make sure you lazy load the gif if
you plan on using it after window load event otherwise it's never going to
happen and you'll just get the endless spinner :D

------
royce
eBay sometimes sends out emails with auction countdowns in them that do
something similar.

The first time that I saw an accurate countdown ticking away in an email, it
surprised the heck out of me.

~~~
ryanwaggoner
You can do it too with services like motionmail.com

------
scrollaway
Hey, cool, I wanted to do the exact same thing the other day but as a
countdown clock. For those saying this has no practical use, a countdown
definitely does :)

~~~
janci
For a countdown, you don't need to stream it, just generate animated countdown
gif.

~~~
gvx
I think they meant "count down to moment X, when something special is
scheduled to take place" rather than "count down from 100".

~~~
janci
Makes sense. I thought of "This email autodestructs in 10... 9" style
countdown.

------
lewis12345
Pretty interesting! Increases in size by ~4KB every second though. Probably
would take a toll on your browser if you left it open for a while. :)

~~~
rzzzt
The server could finish sending frames and let the gif loop after 12/24 hours
have elapsed.

~~~
xamuel
This would fail to account for things like leap seconds

------
superasn
This is great. If I were to serve this over apache is there a limit on the
connections? I'm asking because I'm assuming there is only a specific number
of concurrent connections per child in apache(?).

So if gif 2 is embedded in 100 sites will it bring my server down since
children are not closing connections?

~~~
def-
I had problems with Haskell after 1024 open sockets, but compiling with ghc
-threaded fixed them. Other than that, no problems encountered yet. (using
nginx as proxy)

------
LeoPanthera
Doesn't seem to work in iPhone safari. Displays the time you loaded the page
but doesn't update.

~~~
def-
Too bad. I only tested with Firefox, Chrome and Android. You could try
[http://hookrace.net:5002/](http://hookrace.net:5002/) directly

Edit: I have now added some cache-control directives, maybe they help

------
otterpro
Also check out [https://github.com/ErikvdVen/php-
gif](https://github.com/ErikvdVen/php-gif) It generates real-time GIF images
with PHP, such as countdown, etc.

------
indescions_2017
Am still waiting for it to finish looping ;)

There's probably a cheap optimization in there somewhere. Diffing frames on
each tick, but for that size it probably doesn't matter. Thanks for the link
to GifStream!

------
homero
It's slow by 4 seconds

~~~
def-
I notice that it has some problems with lots of visitors and some browsers
that delay showing the next frame of the gif. I guess that's what happens when
you misuse GIFs

------
yogthos
[gifsockets]([https://github.com/videlalvaro/gifsockets](https://github.com/videlalvaro/gifsockets))
is another version of this

------
rad_gruchalski
The code is constantly 1 second behind.

------
mrcactu5
> It is written in Haskell and works by dynamically generating each frame of
> the GIF and slowly feeding them over the HTTP connection.

This seems rather difficult. These are dynamically generated. There are 24
_60_ 60=86400 possible slides, but at download time, we have to find the
correct starting point. Did I get that right?

~~~
pygy_
What would the difficulty be? You pick the first image by looking at the
server time then send the next frames once per second...

You may optimize it by sending diffed frames (IIRC the gif format allows one
to only update the pixels that change from one frame to the next). You could
even pre-generate both sets of images (full frame and diff) and use the script
to send the right frame at the right time.

------
petrikapu
finally useful haskell project

------
_71_
McAuliffe Counters Critics of Police Response to Charlottesville Violence
[http://www.scout.com/Board/102743/Contents/fRee-Colts-Vs-
Lio...](http://www.scout.com/Board/102743/Contents/fRee-Colts-Vs-Lions-Li-ve-
STream-2017-NFL-Game-TV-106089255)

------
lisper
I don't understand why this is getting so much attention. From the
description:

"[It] works by dynamically generating each frame of the GIF and slowly feeding
them over the HTTP connection."

So there is nothing (AFAICT) new or interesting going on here. It's just an
animation generated by the server in real time that happens to be formatted as
a gif. It's no different from what many low-end web-enabled security cameras
do.

~~~
Tepix
No, low end security cameras send separate JPEG images (sometimes as a MJPEG
stream), not GIF frames. GIF frames would be terrible for the cameras because
of the limited colour palette.

~~~
lisper
OK, well, that's true. But is sending an animated gif instead of jpegs really
that much of an innovation? If I did the same thing using, say, APNGs would HN
go crazy over that?

~~~
Retra
Nobody is going crazy, they are simply learning things. If you've got
something to teach, HN will probably like it.

Though I'm not sure why you even care what HN likes. It certainly isn't
measured in units of innovation, as you seem to think it should.

~~~
lisper
Maybe "going crazy" was overstating it. But it has >350 upvotes, and a lot of
comments like this:

[https://news.ycombinator.com/item?id=14997202](https://news.ycombinator.com/item?id=14997202)

"This is absolutely awesome."

I'm just trying to understand why people think it's "absolutely awesome." It
seems, at best, mildly interesting to me.

~~~
always_good
This is textbook middlebrow dismissal.

Let's turn it around. Why do you think it's so important that we understand
how unimpressed and uninterested you are?

This is a simple, accessible project that people think is fun. They upvoted
it.

~~~
lisper
OK.

------
Markoff
interesting concept, but not very practical compared to www.time.is

------
charlex815
_Waits for the Node.js implementation_

------
archergod
it is one of those thing you do because you can do that. If you try to open
the GIF only it won't work well and if you try to save it as image it won't
work.

for me it has no real application that I can think of, it consume lot of
bandwidth and processing even for small size gif.

good knowledge for developer, I certainly cannot even think in that line. But
no use of it in current form.

