gotty/js/spice-web-client/lib/images/jsquic_uncompress.js

511 lines
14 KiB
JavaScript
Raw Normal View History

function QUIC_UNCOMPRESS_RGB(encoder, channels, bpc, type) {
quic_uncompress_row0(encoder, channels, bpc, type);
encoder.row_completed();
var rgb_state = encoder.rgb_state;
var height = encoder.height;
for (var row = 1; row < height; row++) {
quic_uncompress_row(encoder, channels, bpc, type, rgb_state);
encoder.row_completed();
}
}
function quic_uncompress_row(encoder, channels, bpc, type, rgb_state) {
var bpc_mask = wdi.JSQuic.BPC_MASK[type];
var pos = 0;
var width = encoder.width;
while ((wdi.JSQuic.wmimax > rgb_state.wmidx) && (rgb_state.wmileft <= width)) {
if (rgb_state.wmileft) {
uncompress_row_seg(
encoder,
pos,
pos + rgb_state.wmileft,
bpc,
bpc_mask,
type,
rgb_state
);
pos += rgb_state.wmileft;
width -= rgb_state.wmileft;
}
rgb_state.wmidx++;
wdi.JSQuic.set_wm_trigger(rgb_state);
rgb_state.wmileft = wdi.JSQuic.wminext;
}
if (width) {
uncompress_row_seg(
encoder,
pos,
pos + width,
bpc,
bpc_mask,
type,
rgb_state
);
if (wdi.JSQuic.wmimax > encoder.rgb_state.wmidx) {
rgb_state.wmileft -= width;
}
}
}
function SAME_PIXEL(i, result) {
if(result[i-4] === result[i] && result[i-3] === result[i+1] &&
result[i-2] === result[i+2]) {
return true;
}
return false;
}
function RLE_PRED(i, encoder, offset, currentOffset, run_index) {
if(run_index !== i && i > 2) {
if(SAME_PIXEL(offset, encoder.result)) { //fila de arriba
var pr = currentOffset + ((i-1)*4);
if(SAME_PIXEL(pr, encoder.result)) { //pixel de la izquierda
return true;
}
}
}
return false;
}
function uncompress_row_seg(encoder, i, end, bpc, bpc_mask, type, rgb_state) {
var channel_r = encoder.channels[0];
var channel_g = encoder.channels[1];
var channel_b = encoder.channels[2];
var buckets_ptrs_r = channel_r._buckets_ptrs;
var buckets_ptrs_g = channel_g._buckets_ptrs;
var buckets_ptrs_b = channel_b._buckets_ptrs;
var correlate_row_r = channel_r.correlate_row;
var correlate_row_g = channel_g.correlate_row;
var correlate_row_b = channel_b.correlate_row;
var stopidx = 0;
var waitmask = wdi.JSQuic.bppmask[rgb_state.wmidx];
var run_index = 0;
var run_end = 0;
var rle = false;
var computedWidth = encoder.computedWidth;
var offset = ((encoder.rows_completed-1) * computedWidth);
var currentOffset = ((encoder.rows_completed) * computedWidth);
var result = encoder.result;
var resultData = encoder.resultData;
var i_1,i_4; //for performance improvments
var xlatL2U = wdi.xlatL2U;
var pr, pg, pb;
var prevCorrelatedR, prevCorrelatedG, prevCorrelatedB;
var eatbits = encoder.eatbits;
var tabrand = wdi.JSQuic.tabrand;
var decode_run = wdi.JSQuic.decode_run;
var ret, codewordlen;
var cnt = encoder.cnt;
var pxCnt = encoder.pxCnt;
var bppmask = wdi.JSQuic.bppmask;
if (!i) {
pr = UNCOMPRESS_ONE_0(channel_r, encoder, bpc_mask, offset);
pg = UNCOMPRESS_ONE_0(channel_g, encoder, bpc_mask, offset);
pb = UNCOMPRESS_ONE_0(channel_b, encoder, bpc_mask, offset);
prevCorrelatedR = correlate_row_r[0];
prevCorrelatedG = correlate_row_g[0];
prevCorrelatedB = correlate_row_b[0];
//inlined appendPixel
resultData[pxCnt++] =
(255 << 24) | // alpha
(pb << 16) | // blue
(pg << 8) | // green
pr; // red
cnt += 4;
if (rgb_state.waitcnt) {
--rgb_state.waitcnt;
} else {
rgb_state.waitcnt = (tabrand.call(wdi.JSQuic, rgb_state) & waitmask);
UPDATE_MODEL(0, encoder, bpc, correlate_row_r, correlate_row_g, correlate_row_b);
}
stopidx = ++i + rgb_state.waitcnt;
} else {
stopidx = i + rgb_state.waitcnt;
pr = result[cnt-4];
pg = result[cnt-3];
pb = result[cnt-2];
prevCorrelatedR = correlate_row_r[i-1];
prevCorrelatedG = correlate_row_g[i-1];
prevCorrelatedB = correlate_row_b[i-1];
}
while(true) {
while (stopidx < end) {
i_4 = offset + i*4;
for (; i <= stopidx; i++) {
rle = RLE_PRED(i, encoder, i_4, currentOffset, run_index);
if(rle) break;
i_1 = i-1;
/////////////////////// INLINING UNCOMPRESS_ONE
//r
ret = golomb_decoding(buckets_ptrs_r[prevCorrelatedR].bestcode,
encoder.io_word, bppmask);
prevCorrelatedR = ret[0];
codewordlen = ret[1];
correlate_row_r[i] = prevCorrelatedR;
pr = ((((xlatL2U[prevCorrelatedR] +
((pr +
result[i_4]) >>> 1))
& bpc_mask
)));
eatbits.call(encoder, codewordlen);
//g
ret = golomb_decoding(buckets_ptrs_g[prevCorrelatedG].bestcode,
encoder.io_word, bppmask);
prevCorrelatedG = ret[0];
codewordlen = ret[1];
correlate_row_g[i] = prevCorrelatedG;
pg = ((((xlatL2U[prevCorrelatedG] +
((pg +
result[i_4 + 1]) >>> 1))
& bpc_mask
)));
eatbits.call(encoder, codewordlen);
//b
ret = golomb_decoding(buckets_ptrs_b[prevCorrelatedB].bestcode,
encoder.io_word, bppmask);
prevCorrelatedB = ret[0];
codewordlen = ret[1];
correlate_row_b[i] = prevCorrelatedB;
pb = ((((xlatL2U[prevCorrelatedB] +
((pb +
result[i_4 + 2]) >>> 1))
& bpc_mask
)));
eatbits.call(encoder, codewordlen);
////////////////////// END INLINING
/**
pr = UNCOMPRESS_ONE(channel_r, i, i_1, i_4, bpc_mask, encoder, correlate_row_r, offset, result, 0, xlatL2U, buckets_ptrs_r, pr);
pg = UNCOMPRESS_ONE(channel_g, i, i_1, i_4, bpc_mask, encoder, correlate_row_g, offset, result, 1, xlatL2U, buckets_ptrs_g, pg);
pb = UNCOMPRESS_ONE(channel_b, i, i_1, i_4, bpc_mask, encoder, correlate_row_b, offset, result, 2, xlatL2U, buckets_ptrs_b, pb);
**/
//this is inlined appendPixel
resultData[pxCnt++] =
(255 << 24) | // alpha
(pb << 16) | // blue
(pg << 8) | // green
pr; // red
cnt += 4;
i_4 += 4;
}
if(!rle) {
UPDATE_MODEL(stopidx, encoder, bpc, correlate_row_r, correlate_row_g, correlate_row_b);
stopidx = i + (tabrand.call(wdi.JSQuic, rgb_state) & waitmask);
} else {
break;
}
}
if(!rle) {
i_4 = offset + i*4;
for (; i < end; i++) {
rle = RLE_PRED(i, encoder, i_4, currentOffset, run_index);
if(rle) break;
i_1 = i-1;
////////////////////// INLINING UNCOMPRESS_ONE
//r
ret = golomb_decoding(buckets_ptrs_r[prevCorrelatedR].bestcode, encoder.io_word, bppmask);
prevCorrelatedR = ret[0];
codewordlen = ret[1];
correlate_row_r[i] = prevCorrelatedR;
pr = ((((xlatL2U[prevCorrelatedR] +
((pr +
result[i_4]) >>> 1))
& bpc_mask
)));
eatbits.call(encoder, codewordlen);
//g
ret = golomb_decoding(buckets_ptrs_g[prevCorrelatedG].bestcode, encoder.io_word, bppmask);
prevCorrelatedG = ret[0];
codewordlen = ret[1];
correlate_row_g[i] = prevCorrelatedG;
pg = ((((xlatL2U[prevCorrelatedG] +
((pg +
result[i_4 + 1]) >>> 1))
& bpc_mask
)));
eatbits.call(encoder, codewordlen);
//b
ret = golomb_decoding(buckets_ptrs_b[prevCorrelatedB].bestcode, encoder.io_word, bppmask);
prevCorrelatedB = ret[0];
codewordlen = ret[1];
correlate_row_b[i] = prevCorrelatedB;
pb = ((((xlatL2U[prevCorrelatedB] +
((pb +
result[i_4 + 2]) >>> 1))
& bpc_mask
)));
eatbits.call(encoder, codewordlen);
///////////////////// END INLINING
/**
pr = UNCOMPRESS_ONE(channel_r, i, i_1, i_4, bpc_mask, encoder, correlate_row_r, offset, result, 0, xlatL2U, buckets_ptrs_r, pr);
pg = UNCOMPRESS_ONE(channel_g, i, i_1, i_4, bpc_mask, encoder, correlate_row_g, offset, result, 1, xlatL2U, buckets_ptrs_g, pg);
pb = UNCOMPRESS_ONE(channel_b, i, i_1, i_4, bpc_mask, encoder, correlate_row_b, offset, result, 2, xlatL2U, buckets_ptrs_b, pb);
**/
//this is inlined apendPixel
resultData[pxCnt++] =
(255 << 24) | // alpha
(pb << 16) | // blue
(pg << 8) | // green
pr; // red
cnt += 4;
i_4 += 4;
}
if(!rle) {
rgb_state.waitcnt = stopidx - end;
encoder.cnt = cnt;
encoder.pxCnt = pxCnt;
return;
}
}
//RLE
rgb_state.waitcnt = stopidx - i;
run_index = i;
run_end = i + decode_run.call(wdi.JSQuic, encoder);
for (; i < run_end; i++) {
//this is inlined appendPixel
resultData[pxCnt++] =
(255 << 24) | // alpha
(pb << 16) | // blue
(pg << 8) | // green
pr; // red
cnt += 4;
}
if (i === end) {
encoder.cnt = cnt;
encoder.pxCnt = pxCnt;
return;
}
i_1 = i-1;
prevCorrelatedR = correlate_row_r[i_1];
prevCorrelatedG = correlate_row_g[i_1];
prevCorrelatedB = correlate_row_b[i_1];
stopidx = i + rgb_state.waitcnt;
rle = false;
//END RLE
}
}
function quic_uncompress_row0(encoder, channels, bpc, type) {
var bpc_mask = wdi.JSQuic.BPC_MASK[type];
var pos = 0;
var width = encoder.width;
while ((wdi.JSQuic.wmimax > encoder.rgb_state.wmidx) && (encoder.rgb_state.wmileft <= width)) {
if (encoder.rgb_state.wmileft) {
uncompress_row0_seg(
encoder,
pos,
pos + encoder.rgb_state.wmileft,
wdi.JSQuic.bppmask[encoder.rgb_state.wmidx],
bpc,
bpc_mask,
type
);
pos += encoder.rgb_state.wmileft;
width -= encoder.rgb_state.wmileft;
}
encoder.rgb_state.wmidx++;
wdi.JSQuic.set_wm_trigger(encoder.rgb_state);
encoder.rgb_state.wmileft = wdi.JSQuic.wminext;
}
if (width) {
uncompress_row0_seg(
encoder,
pos,
pos + width,
wdi.JSQuic.bppmask[encoder.rgb_state.wmidx],
bpc,
bpc_mask,
type
);
if (wdi.JSQuic.wmimax > encoder.rgb_state.wmidx) {
encoder.rgb_state.wmileft -= width;
}
}
}
function uncompress_row0_seg(encoder, i, end, waitmask, bpc, bpc_mask, type) {
var channel_r = encoder.channels[0];
var channel_g = encoder.channels[1];
var channel_b = encoder.channels[2];
var correlate_row_r = channel_r.correlate_row;
var correlate_row_g = channel_g.correlate_row;
var correlate_row_b = channel_b.correlate_row;
var stopidx = 0;
var pr, pg, pb;
if (!i) {
pr = UNCOMPRESS_ONE_ROW0_0(channel_r);
pg = UNCOMPRESS_ONE_ROW0_0(channel_g);
pb = UNCOMPRESS_ONE_ROW0_0(channel_b);
encoder.appendPixel(pr, pg, pb);
if (encoder.rgb_state.waitcnt) {
--encoder.rgb_state.waitcnt;
} else {
encoder.rgb_state.waitcnt = (wdi.JSQuic.tabrand(encoder.rgb_state) & waitmask);
UPDATE_MODEL(0, encoder, bpc, correlate_row_r, correlate_row_g, correlate_row_b);
}
stopidx = ++i + encoder.rgb_state.waitcnt;
} else {
stopidx = i + encoder.rgb_state.waitcnt;
}
while (stopidx < end) {
for (; i <= stopidx; i++) {
pr = UNCOMPRESS_ONE_ROW0(channel_r, i, bpc_mask, encoder, correlate_row_r, pr);
pg = UNCOMPRESS_ONE_ROW0(channel_g, i, bpc_mask, encoder, correlate_row_g, pg);
pb = UNCOMPRESS_ONE_ROW0(channel_b, i, bpc_mask, encoder, correlate_row_b, pb);
encoder.appendPixel(pr, pg, pb);
}
UPDATE_MODEL(stopidx, encoder, bpc, correlate_row_r, correlate_row_g, correlate_row_b);
stopidx = i + (wdi.JSQuic.tabrand(encoder.rgb_state) & waitmask);
}
for (; i < end; i++) {
pr = UNCOMPRESS_ONE_ROW0(channel_r, i, bpc_mask, encoder, correlate_row_r, pr);
pg = UNCOMPRESS_ONE_ROW0(channel_g, i, bpc_mask, encoder, correlate_row_g, pg);
pb =UNCOMPRESS_ONE_ROW0(channel_b, i, bpc_mask, encoder, correlate_row_b, pb);
encoder.appendPixel(pr, pg, pb);
}
encoder.rgb_state.waitcnt = stopidx - end;
}
function UNCOMPRESS_ONE_0(channel, encoder, bpc_mask, offset) {
var ret, codewordlen;
channel.oldFirst = channel.correlate_row[0];
ret = golomb_decoding(find_bucket(channel,
channel.correlate_row[0]).bestcode, encoder.io_word, wdi.JSQuic.bppmask);
channel.correlate_row[0] = ret[0];
codewordlen = ret[1];
var residuum = wdi.xlatL2U[channel.correlate_row[0]];
var prev = encoder.result[offset + channel.num_channel]; //PIXEL_B
var resultpixel = ((residuum + prev) & bpc_mask);
encoder.eatbits(codewordlen);
return resultpixel;
}
function UNCOMPRESS_ONE(channel, i, i_1, i_4, bpc_mask, encoder, correlate_row, offset, result, num_channel, xlatL2U, buckets_ptrs, prev_pixel) {
var ret, codewordlen;
ret = golomb_decoding(buckets_ptrs[correlate_row[i_1]].bestcode, encoder.io_word, wdi.JSQuic.bppmask);
var data = ret[0];
codewordlen = ret[1];
correlate_row[i] = data;
var ret = ((((xlatL2U[data] +
((prev_pixel +
result[offset + (i_4) + num_channel]) >>> 1))
& bpc_mask
)));
encoder.eatbits(codewordlen);
return ret;
}
function UNCOMPRESS_ONE_ROW0_0(channel) {
var ret, codewordlen;
var encoder = channel.encoder;
ret = golomb_decoding(find_bucket(channel, 0).bestcode, encoder.io_word, wdi.JSQuic.bppmask);
channel.correlate_row[0] = ret[0]
codewordlen = ret[1];
var ret = wdi.xlatL2U[channel.correlate_row[0]];
encoder.eatbits(codewordlen);
return ret;
}
function UNCOMPRESS_ONE_ROW0(channel, i, bpc_mask, encoder, correlate_row, prev_pixel) {
var ret, codewordlen;
ret = golomb_decoding(find_bucket(channel, correlate_row[i-1]).bestcode, encoder.io_word, wdi.JSQuic.bppmask);
correlate_row[i] = ret[0];
codewordlen = ret[1];
var ret = CORELATE_0(encoder, channel, i, bpc_mask, correlate_row, prev_pixel);
encoder.eatbits(codewordlen);
return ret;
}
function CORELATE_0(encoder, channel, curr, bpc_mask, correlate_row, prev_pixel) {
return ((wdi.xlatL2U[correlate_row[curr]] + prev_pixel) & bpc_mask);
}
function PIXEL_A(encoder) {
return encoder.result[encoder.cnt - 4];
}
function PIXEL_B(channel, encoder, pos, offset) {
return encoder.result[offset + (pos*4) + channel.num_channel];
}