As some people know, there was Go2UselessActivity decoder for Libav showcased at FOSDEM (on an ARM-based laptop even). It decoded all known variants of the codec with varying degress of success (i.e. output ranged from being completely garbage to being slightly recognizable). Some guy nicknamed “j-b” was really happy for some unknown reason.
Let’s consider a purely theoretical situation that somebody needs Go2EncountersOfTheWorstKind 2/3 and wants to know how it works (usually it’s either one or another or none). As it’s known already it combines ELS-coded images with JPEG-coded data for some pixels that are coded transparent in ELS. JPEG data, to quote j-b
is boring, so let’s look at ELS image coding.
The coder used is the augmented ELS coder by Douglas M. Withers (still available somewhere in Internet insize OSAUGELS.ZIP) with the same tables (36 jots per byte). The only interesting thing is how the image itself is coded with this binary coder.
- Unsigned values are decoded as unary prefix for number of bits to follow and then the actual value, signed values are coded as unsigned with an usual scheme
x -> 2*x, -x -> 2*x - 1
(zero is explicitly signalled by number of bits being zero of course).
- Pixels are coded as RGB triplets, using median prediction from top, top left and left neighbours if possible. If prediction is used then pixels are coded as differences to
(G, R-G, B-G)
predicted value.
- General image coding is conceptually simple: the image is coded as runs of RGB triplets if possible; in some cases if it’s possible to decode pixel from cache it’s done so. If that’s not possible too then one pixel is coded as described above.
Here’s slightly more detailed image decoding description:
for (y = 0; y < height; y++) {
x = 0;
while (x < width) {
if (x > 1 && y > 0 &&
rgb[x - 1][y] != rgb[x - 2][y] &&
rgb[x - 1][y] != rgb[x ][y - 1] &&
rgb[x - 1][y] != rgb[x - 1][y - 1] &&
rgb[x - 1][y] != rgb[x - 2][y - 1] &&
pixel_in_cache(rgb[x - 1][y]) {
rgb[x][y] = decode_pixel_with_prediction(x, y);
x++;
continue;
}
decode_run(x, y, &run_length, &pix);
if (run_length > 0) {
// pixel value may get changed here
decode_modified_pix(x, y, run_length, &pix);
while (run_length--)
rgb[x++][y] = pix;
} else if (decode_from_cache(&pix)) {
rgb[x][y] = pix;
x++;
} else {
rgb[x][y] = decode_pixel_with_prediction(x, y);
x++;
}
}
}
Hopefully no more information will follow soon.