With the 16-Bit PNGs from Sintel being released I looked for a way to dither them into a format x264 understands.
I tried Imagemagick and ffmpeg (and derivatives) and I failed with both of them to dither the pngs. So I wrote my own crappy tool that does:
1) Read a PNG
2) Convert it to double precision YUV 4:2:0
3) Dithers to 8-bit
Thanks a lot to the guys from libcaca for doing
this study. Since they are only doing dithering to 1-bit images, I adapted it in the way that I only dither the lower 8-bits and use it to decide whether to round up or down.
I implemented or adapted nearly every (appliable) algorithm in that study. My results were, good old ordered dithering with a "void and cluster" generated matrix performed the best (at reasonable speeds). See the last images on
this page for samples. See
here for the usually used algorithms. Floyd steinberg is the one "everyone" uses, x264 uses "Filter Lite". Notice how all of them still have some residual banding, and my tests showed the banding is still visible if you apply it for some scenes in Sintel.
As for the "Void and Cluster" matrix, I used the smaller 14x14 matrix because I didn't want to copy 25x25 values (I didn't implement the void and cluster algorithm).
I also tried
model based dithering. While it had really awesome results, it was just to damn slow for anything above 720p. I took ~8 seconds for one iteration of a 1280x544 image on a single core of my CoreDuo T2300 (1.66Ghz).
To improve still shots, so the dithering noise wasn't static, I used 4 mirrored versions of the same matrix to fake some temporal noise.
So without further ado, here is the source:
http://www.mediafire.com/?1b0yr9jam363gbsIt includes a crappy Makefile for Linux and cross compiling to Windows. It links agains libpng, so you need libpng-dev (and zlib-dev with it) installed, also you need the png++dev header files (because I'm lazy).
For cross compiling I used the following additional files:
http://www.mediafire.com/?4dy47oy46azcj4nThese files includes png++ (BSD license), libpng (libpng License) and zlib (zlib License) header files and files needed for linking.
Here is a windows binary (together with the libpng and zlib dlls):
http://www.mediafire.com/?65kao7c24zaoyo6The program has no real output, but usage is quite simple:
> dither input.png output.yv12 [rotation]
The rotation parameter is optional and takes values from 0-3. It determines what direction the dithering matrix is scanned in. So use it with something like "Framenumber modulo 4".
The output is appended to the output filename. So theoretically you can just call the programm from frame 0 to the last one with the same output file. But since you probably want to call the program more then once in parallel, I used a new file for each input and concatenated them later. You might want to use a compressed filesystem for the temporary yv12 files because they are quite huge (~1MB per 720p frame, ~2.3MB for 1080p)
I'm releasing this under a "do what you want but don't laugh at my code" license. In the source there is only the final dithering algorithm, if youre interested in the others, just ask.
*edit* By the way, those streams can be encoded with those settings via x264:
--demuxer lavf --input-res 1280x544 --input-fmt rawvideo --input-depth 8 --fullrange off --colormatrix bt709
(which I think makes them not yv12 but yuv420 files...)