diff options
author | Jeremy White <jwhite@codeweavers.com> | 2012-06-04 17:22:01 +0300 |
---|---|---|
committer | Alon Levy <alevy@redhat.com> | 2012-06-04 17:22:01 +0300 |
commit | f8f622157c174ba3facc088646484ccba99acc69 (patch) | |
tree | 88d99c83e53fa8509a8ca33a6e9f6bdc015e5791 /lz.js |
initial
Diffstat (limited to 'lz.js')
-rw-r--r-- | lz.js | 158 |
1 files changed, 158 insertions, 0 deletions
@@ -0,0 +1,158 @@ +"use strict"; +/* + Copyright (C) 2012 by Jeremy P. White <jwhite@codeweavers.com> + + This file is part of spice-html5. + + spice-html5 is free software: you can redistribute it and/or modify + it under the terms of the GNU Lesser General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + spice-html5 is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public License + along with spice-html5. If not, see <http://www.gnu.org/licenses/>. +*/ + + +/*---------------------------------------------------------------------------- +** lz.js +** Functions for handling SPICE_IMAGE_TYPE_LZ_RGB +** Adapted from lz.c . +**--------------------------------------------------------------------------*/ +function lz_rgb32_decompress(in_buf, at, out_buf, type, default_alpha) +{ + var encoder = at; + var op = 0; + var ctrl; + var ctr = 0; + + for (ctrl = in_buf[encoder++]; (op * 4) < out_buf.length; ctrl = in_buf[encoder++]) + { + var ref = op; + var len = ctrl >> 5; + var ofs = (ctrl & 31) << 8; + +//if (type == LZ_IMAGE_TYPE_RGBA) +//console.log(ctr++ + ": from " + (encoder + 28) + ", ctrl " + ctrl + ", len " + len + ", ofs " + ofs + ", op " + op); + if (ctrl >= 32) { + + var code; + len--; + + if (len == 7 - 1) { + do { + code = in_buf[encoder++]; + len += code; + } while (code == 255); + } + code = in_buf[encoder++]; + ofs += code; + + + if (code == 255) { + if ((ofs - code) == (31 << 8)) { + ofs = in_buf[encoder++] << 8; + ofs += in_buf[encoder++]; + ofs += 8191; + } + } + len += 1; + if (type == LZ_IMAGE_TYPE_RGBA) + len += 2; + + ofs += 1; + + ref -= ofs; + if (ref == (op - 1)) { + var b = ref; +//if (type == LZ_IMAGE_TYPE_RGBA) console.log("alpha " + out_buf[(b*4)+3] + " dupped into pixel " + op + " through pixel " + (op + len)); + for (; len; --len) { + if (type == LZ_IMAGE_TYPE_RGBA) + { + out_buf[(op*4) + 3] = out_buf[(b*4)+3]; + } + else + { + for (i = 0; i < 4; i++) + out_buf[(op*4) + i] = out_buf[(b*4)+i]; + } + op++; + } + } else { +//if (type == LZ_IMAGE_TYPE_RGBA) console.log("alpha copied to pixel " + op + " through " + (op + len) + " from " + ref); + for (; len; --len) { + if (type == LZ_IMAGE_TYPE_RGBA) + { + out_buf[(op*4) + 3] = out_buf[(ref*4)+3]; + } + else + { + for (i = 0; i < 4; i++) + out_buf[(op*4) + i] = out_buf[(ref*4)+i]; + } + op++; ref++; + } + } + } else { + ctrl++; + + if (type == LZ_IMAGE_TYPE_RGBA) + { +//console.log("alpha " + in_buf[encoder] + " set into pixel " + op); + out_buf[(op*4) + 3] = in_buf[encoder++]; + } + else + { + out_buf[(op*4) + 0] = in_buf[encoder + 2]; + out_buf[(op*4) + 1] = in_buf[encoder + 1]; + out_buf[(op*4) + 2] = in_buf[encoder + 0]; + if (default_alpha) + out_buf[(op*4) + 3] = 255; + encoder += 3; + } + op++; + + + for (--ctrl; ctrl; ctrl--) { + if (type == LZ_IMAGE_TYPE_RGBA) + { +//console.log("alpha " + in_buf[encoder] + " set into pixel " + op); + out_buf[(op*4) + 3] = in_buf[encoder++]; + } + else + { + out_buf[(op*4) + 0] = in_buf[encoder + 2]; + out_buf[(op*4) + 1] = in_buf[encoder + 1]; + out_buf[(op*4) + 2] = in_buf[encoder + 0]; + if (default_alpha) + out_buf[(op*4) + 3] = 255; + encoder += 3; + } + op++; + } + } + + } + return encoder - 1; +} + +function convert_spice_lz_rgb_to_web(context, lz_rgb) +{ + var u8 = new Uint8Array(lz_rgb.data); + var at; + if (lz_rgb.type != LZ_IMAGE_TYPE_RGB32 && lz_rgb.type != LZ_IMAGE_TYPE_RGBA) + return undefined; + + var ret = context.createImageData(lz_rgb.width, lz_rgb.height); + + at = lz_rgb32_decompress(u8, 0, ret.data, LZ_IMAGE_TYPE_RGB32, lz_rgb.type != LZ_IMAGE_TYPE_RGBA); + if (lz_rgb.type == LZ_IMAGE_TYPE_RGBA) + lz_rgb32_decompress(u8, at, ret.data, LZ_IMAGE_TYPE_RGBA, false); + + return ret; +} |