"use strict"; /* Copyright (C) 2012 by Jeremy P. White 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 . */ import { Constants } from './enums.js'; /*---------------------------------------------------------------------------- ** 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; var i = 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 == Constants.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 == Constants.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 == Constants.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 == Constants.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 == Constants.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 flip_image_data(img) { var wb = img.width * 4; var h = img.height; var temp_h = h; var buff = new Uint8Array(img.width * img.height * 4); while (temp_h--) { buff.set(img.data.subarray(temp_h * wb, (temp_h + 1) * wb), (h - temp_h - 1) * wb); } img.data.set(buff); } function convert_spice_lz_to_web(context, lz_image) { var at; if (lz_image.type === Constants.LZ_IMAGE_TYPE_RGB32 || lz_image.type === Constants.LZ_IMAGE_TYPE_RGBA) { var u8 = new Uint8Array(lz_image.data); var ret = context.createImageData(lz_image.width, lz_image.height); at = lz_rgb32_decompress(u8, 0, ret.data, Constants.LZ_IMAGE_TYPE_RGB32, lz_image.type != Constants.LZ_IMAGE_TYPE_RGBA); if (!lz_image.top_down) flip_image_data(ret); if (lz_image.type == Constants.LZ_IMAGE_TYPE_RGBA) lz_rgb32_decompress(u8, at, ret.data, Constants.LZ_IMAGE_TYPE_RGBA, false); } else if (lz_image.type === Constants.LZ_IMAGE_TYPE_XXXA) { var u8 = new Uint8Array(lz_image.data); var ret = context.createImageData(lz_image.width, lz_image.height); lz_rgb32_decompress(u8, 0, ret.data, Constants.LZ_IMAGE_TYPE_RGBA, false); } else return undefined; return ret; } export { convert_spice_lz_to_web, };