Skip to content

Instantly share code, notes, and snippets.

@djg
Created November 28, 2013 21:37
Show Gist options
  • Save djg/7698472 to your computer and use it in GitHub Desktop.
Save djg/7698472 to your computer and use it in GitHub Desktop.
Yeah, umm. Thanks to @BrendanEich for <<,>>>,&,| ;-)
function uncompressETC2Block(destBuffer, destX, destY, destWidth, src) {
'use strict';
var xx, yy, basecols;
function extend_4to8bits(r, g, b) {
return [
(r & 0xf0) | ((r >> 4) & 0x0f),
(g & 0xf0) | ((g >> 4) & 0x0f),
(b & 0xf0) | ((b >> 4) & 0x0f),
255
];
}
function extend_5to8bits(r, g, b) {
return [
(r & 0xf8) | ((r >> 5) & 0x07),
(g & 0xf8) | ((g >> 5) & 0x07),
(b & 0xf8) | ((b >> 5) & 0x07),
255
];
}
function extend_676to8bits(r, g, b) {
return [
(r & 0xfc) | ((r >> 6) & 0x03),
(g & 0xfe) | ((g >> 7) & 0x01),
(b & 0xfc) | ((b >> 6) & 0x03),
255
];
}
function base_colors(src, mode) {
function compare(c1, c2) {
return (c1[0] * 65536 + c1[1] * 256 + c1[2]) >=
(c2[0] * 65536 + c2[1] * 256 + c2[2]);
}
var col_1, col_2, didx, d;
if (mode === 'I') {
col_1 = extend_4to8bits(src[0], src[1], src[2]);
col_2 = extend_4to8bits(src[0] << 4, src[1] << 4, src[2] << 4);
return [ col_1, col_2 ];
}
if (mode === 'D') {
col_1 = extend_5to8bits(src[0], src[1], src[2]);
col_2 = extend_5to8bits(src[0] + 8 * _deltatable[(src[0] & 0x7)],
src[1] + 8 * _deltatable[(src[1] & 0x7)],
src[2] + 8 * _deltatable[(src[2] & 0x7)]);
return [ col_1, col_2 ];
}
if (mode === 'T') {
col_1 = extend_4to8bits(
((src[0] & 0x18) << 3) | ((src[0] & 0x3) << 4),
src[1],
src[1] << 4
);
col_2 = extend_4to8bits(src[2], src[2] << 4, src[3]);
didx = ((src[3] & 0x0c) >> 1) | (src[3] & 0x01);
d = _disttable[didx];
return [ col_1, offset_color(col_2, d), col_2, offset_color(col_2, -d) ];
}
if (mode === 'H') {
col_1 = extend_4to8bits(
src[0] << 1,
(src[0] << 5) | (src[1] & 0x10),
((src[1] & 0x08) << 4) | ((src[1] & 0x03) << 5) | (src[2] >>> 3)
);
col_2 = extend_4to8bits(
src[2] << 1,
(src[2] << 5) | (src[3] >>> 3),
src[3] << 1
);
didx = (src[3] & 0x04) |
((src[3] & 0x01) << 1) |
(compare(col_1, col_2) ? 0x1 : 0x0);
d = _disttable[didx];
return [ offset_color(col_1, d),
offset_color(col_1, -d),
offset_color(col_2, d),
offset_color(col_2, -d) ];
}
if (mode === 'P') {
var O = extend_676to8bits(src[0] << 1,
(src[0] << 7) | (src[1] & 0x7e),
(src[1] << 7) | ((src[2] << 2) & 0x60) | ((src[2] << 3) & 0x18) | (src[3] >>> 5));
var H = extend_676to8bits(((src[3] << 1) & 0xf8) | ((src[3] << 2) & 0x04),
src[4],
(src[4] << 7) | (src[5] >>> 1));
var V = extend_676to8bits((src[5] << 5) | (src[6] >>> 3),
(src[6] << 3) | (src[7] >>> 5),
src[7] << 2);
return [ O, H, V ];
}
return [];
}
function mode(src) {
if ((src[3] & 0x2) === 0) { return 'I'; }
// Check R+dR outside of [0,31]
var R = (src[0] >>> 3) + _deltatable[(src[0] & 0x7)];
if (R & ~31) { return 'T'; }
// Check G+dG outside of [0,31]
var G = (src[1] >>> 3) + _deltatable[(src[1] & 0x7)];
if (G & ~31) { return 'H'; }
// Check B+dB outside of [0,31]
var B = (src[2] >>> 3) + _deltatable[(src[2] & 0x7)];
if (B & ~31) { return 'P'; }
return 'D';
}
function flip(src) {
return (src[3] & 0x1) === 0x1;
}
function subblock_modtable(src, sb) {
var shift = (sb ? 2 : 5);
var idx = (src[3] >> shift) & 0x7;
return _modtable[idx];
}
function interleave_table_indices(src) {
var result =
(_sl[src[7] & 0xf] | _sh[src[5] & 0xf]) |
((_sl[(src[7] >> 4) & 0xf] | _sh[(src[5] >> 4) & 0xf]) << 8) |
((_sl[src[6] & 0xf] | _sh[src[4] & 0xf]) << 16) |
((_sl[(src[6] >> 4) & 0xf] | _sh[(src[4] >> 4) & 0xf]) << 24);
return result;
}
function subblock(n, flip) {
var mask = flip ? 0x2 : 0x8;
return (n & mask) ? 1 : 0;
}
function clamp0255(x) { return Math.min(Math.max(0, x), 255); }
var m = mode(src);
basecols = base_colors(src, m);
var alpha = 255;
var flipbit = flip(src);
var table_indices = interleave_table_indices(src);
var n = 0;
for (xx = 0; xx < 4; ++xx) {
for (yy = 0; yy < 4; ++yy) {
var dstOff = ((destY + yy) * destWidth + destX + xx) * 4;
var col;
if (m === 'I' || m === 'D') {
var sb = subblock(n, flipbit);
var mod = subblock_modtable(src, sb);
var offset = mod[(table_indices & 0x3)];
col = offset_color(basecols[sb], offset);
} else if (m === 'T' || m === 'H') {
col = basecols[(table_indices & 0x3)];
} else if (m === 'P') {
var x = n >>> 2;
var y = n & 0x03;
col = [
clamp0255((x * (basecols[1][0] - basecols[0][0]) +
y * (basecols[2][0] - basecols[0][0]) +
4 * basecols[0][0] + 2) >> 2),
clamp0255((x * (basecols[1][1] - basecols[0][1]) +
y * (basecols[2][1] - basecols[0][1]) +
4 * basecols[0][1] + 2) >> 2),
clamp0255((x * (basecols[1][2] - basecols[0][2]) +
y * (basecols[2][2] - basecols[0][2]) +
4 * basecols[0][2] + 2) >> 2),
255
];
}
destBuffer[dstOff] = col[0];
destBuffer[dstOff + 1] = col[1];
destBuffer[dstOff + 2] = col[2];
destBuffer[dstOff + 3] = alpha;
table_indices >>= 2;
n++;
}
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment