
Generating Images in JavaScript Without Using the Canvas API - petercooper
https://medium.com/the-guardian-mobile-innovation-lab/generating-images-in-javascript-without-using-the-canvas-api-77f3f4355fad
======
zbjornson
Cool. Nice, creative work. Indexed PNGs seem unfortunately under utilized.

I happen to have just opened a PR to support indexed PNGs in node-canvas (HTML
Canvas impl for node) based roughly on the proposed pixelFormat API [1,2] for
the same reason that the space savings can be immense.

It's also straightforward to change the palette of an indexed PNG after it's
encoded because you don't need to re-compress the body. This lets you do cool
tricks with recoloring images.

[1] [https://github.com/Automattic/node-
canvas/pull/935](https://github.com/Automattic/node-canvas/pull/935) [2]
[https://github.com/WICG/canvas-color-
space/blob/master/Canva...](https://github.com/WICG/canvas-color-
space/blob/master/CanvasColorSpaceProposal.md)

~~~
TazeTSchnitzel
Decent image editors etc do often output indexed PNGs. And thankfully, modern
viewers do actually support them.

------
VikingCoder
I can't even tell you how many times I've re-implemented PPM file format in
whatever language, to produce an image file, when no libraries were available
to me. Dozens, easily.

~~~
striking
That's an excellent idea. I wonder if it'd work with this scenario.

------
mnutt
It's a really clever solution, kudos to them. Is there a limitation why they
couldn't just have the notification point to a remote URL and update server-
side using whatever solution they wanted? It wouldn't have been as elegant but
may have been easier to build.

~~~
_alastair
The main reason is that the phone will download the image each time you post a
notification, and with 650 alerts throughout the night (for 650
constituencies) the user would end up downloading a lot of data with very
little to show for it (since newer notifications replace the older ones).

But to add to that, it needed to be customised for different screen sizes. So
we'd have to have generated a lot of versions server side.

------
tambourine_man
I handcrafted GIFs back in the day, mostly by looking at generated files and
fiddling with the hex. Lots of fun.

I'm curious if it would've been simpler to use it, albeit less efficient.

------
moron4hire
I had done a similar thing for PCM WAV files before Web Audio API was really a
thing: [http://www.seanmcbeth.com/synth/](http://www.seanmcbeth.com/synth/)

Pretty sure that only runs in Chrome anymore.

------
seanwilson
Maybe I'm missing something but why not use SVG for some of this? Would be
perfect for the lozenge pictures.

~~~
_alastair
You can't use an SVG as an image in a notification. A real shame as it would
have solved all the device pixel ratio problems, but the SVG spec is
absolutely huge (and includes stuff like animation) so I'm not _overly_
surprised that Android doesn't support it.

~~~
seanwilson
Hmm, I'm wondering if there's a way now to render an SVG (not the full spec)
within a service worker e.g. using PngPong with
[https://github.com/canvg/canvg](https://github.com/canvg/canvg)

~~~
_alastair
Huh! That's a really fascinating library. My gut instinct is still that it
would be a heavy lift, though. Without the Canvas API in the middle you'd need
to reimplement pixel by pixel drawing of different shape/curves (PngPong
literally only draws squares and copies sections of other images) anti-
aliasing, etc. etc.

It would be a fascinating thing to work on, but the OffscreenCanvas API is
coming to Chrome[1], so I suspect it would end up being a lot of work that
would be obselete after not all that much time.

[1]
[https://www.chromestatus.com/feature/5424182347169792](https://www.chromestatus.com/feature/5424182347169792)

~~~
joshmarinacci
This might work for you. pure JS impl of canvas

[https://github.com/joshmarinacci/node-
pureimage](https://github.com/joshmarinacci/node-pureimage)

~~~
_alastair
Interesting, I'll have to take a look. Thanks!

------
18nleung
I tried making PNGs before from bytes but got stuck on CRC generation - the
math just seemed way over my head.

Is there a simple way to explain CRC for someone with just a high school
mathematics background?

~~~
karlding
I've always found "A Painless Guide to CRC Error Detection Algorithms" [1]
from the zlib site pretty useful and easy to understand. Once you understand
polynomial division, things start making a lot more sense.

[1] [https://zlib.net/crc_v3.txt](https://zlib.net/crc_v3.txt)

~~~
18nleung
Thank you, this looks great.

------
bradneuberg
Nice creative hackery in the browser! Always great to see well written blog
posts on pushing web browsers in new unexpected directions.

------
finchisko
Hat off. Nice piece of engineering thinking.

------
Xoros
Despite the fact that it's pretty good stuff, shouldn't the title says it's
for Android notification ?

~~~
andrewla
That was the goal, but the underlying library is general-purpose.

Writing a minimal uncompressed PNG writer from scratch is a fun exercise; the
spec is pretty clear and the only tricky part, really, is getting the
uncompressed zlib part right, especially since the block sizes are
undocumentedly little-endian, while everything else is big-endian.

Self-contained code for image generation and consumption can be pretty useful.
It's one of the reasons that I like farbfeld, suckless's incredible simple
binary image format, because libraries for processing it are essentially
unnecessary since the format itself is so straightforward.

~~~
_alastair
> especially since the block sizes are undocumentedly little-endian, while
> everything else is big-endian.

Yes! That stumped me for a long time. Along the way to solving it I found this
great Stack Overflow answer where the creator of ADLER32 popped in to give
some advice:

[https://stackoverflow.com/questions/32633486/why-are-png-
def...](https://stackoverflow.com/questions/32633486/why-are-png-deflate-
block-lengths-being-ignored#comment53120790_32635822)

"Also just realized that you are _that_ Mark Adler."

