Skip to content

The last bit of C has fallen

Compare
Choose a tag to compare
@kornelski kornelski released this 24 Oct 03:03
· 62 commits to main since this release

gif.ski was originally meant to be just the highest-quality GIF maker, but over time I also made it generate smaller files. Now it's probably the most technically advanced GIF compressor, if I say so myself.

The key to good GIF compression is making LZW algorithm lossy. In 2014, I wrote a patch that added lossy compression to gifsicle. Gifsicle is a GIF optimization tool created in 1998, so I can't blame them for not using Rust. Of course, I wanted to use that lossy compression in gif.ski too, so I've made gifsicle usable as a Rust crate.

Rust already had a gif encoder, so bringing all of the gifsicle's code seemed unnecessary. I only wanted the lossy LZW bit, so I've made the Rust gif library accept data from other compressors, and used only a couple of gifsicle's C functions for compression.

The lossy LZW compressor was still my 2014 hacked-together C — until yesterday. I've rewritten it in Rust.

The rewritten code gives exactly the same, bit-identical output. Usually, when people rewrite projects it's hard to compare results to the original, because the rewrites change and reinvent things along the way. This time it's apples to apples. I made sure it works exactly the same. I even reimplemented an integer overflow bug and quirks caused by use linked lists. The result is… the same performance, and the same binary size, within margin of error. You don't need to rush to upgrade! On one hand this isn't surprising — it's the same algorithm, and Rust has C-like performance as advertised. OTOH I used mostly idiomatic Rust, and did not try to make it super optimized. The original C code did clever things with memory pools and linked lists, and I've swapped it all for Vecs in enums.

Aside from ffmpeg, which I'm not rewriting, gif.ski is now 100% pure Rust. It makes it a bit easier to build it. The x86-64 MUSL/Linux binary has been built on my ARM Mac. Since the code is now in a form I find easier to refactor, later I'll work on improving quality of its lossy dithering, because for some reason I'm determined to squeeze every last possible bit out of this prehistoric video format.