diff --git a/include/base64.js b/include/base64.js index 87336127..5a6890ad 100644 --- a/include/base64.js +++ b/include/base64.js @@ -10,16 +10,16 @@ var Base64 = { /* Convert data (an array of integers) to a Base64 string. */ -toBase64Table : 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/'.split(''), +toBase64Table : 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/='.split(''), base64Pad : '=', encode: function (data) { "use strict"; var result = ''; var toBase64Table = Base64.toBase64Table; - var base64Pad = Base64.base64Pad; - var length = data.length; - var i; + var length = data.length + var lengthpad = (length%3); + var i = 0, j = 0; // Convert every three bytes to 4 ascii characters. /* BEGIN LOOP */ for (i = 0; i < (length - 2); i += 3) { @@ -31,17 +31,18 @@ encode: function (data) { /* END LOOP */ // Convert the remaining 1 or 2 bytes, pad out to 4 characters. - if (length%3) { - i = length - (length%3); - result += toBase64Table[data[i] >> 2]; - if ((length%3) === 2) { - result += toBase64Table[((data[i] & 0x03) << 4) + (data[i+1] >> 4)]; - result += toBase64Table[(data[i+1] & 0x0f) << 2]; - result += base64Pad; - } else { - result += toBase64Table[(data[i] & 0x03) << 4]; - result += base64Pad + base64Pad; - } + if (lengthpad === 2) { + j = length - lengthpad; + result += toBase64Table[data[j] >> 2]; + result += toBase64Table[((data[j] & 0x03) << 4) + (data[j+1] >> 4)]; + result += toBase64Table[(data[j+1] & 0x0f) << 2]; + result += toBase64Table[64]; + } else if (lengthpad === 1) { + j = length - lengthpad; + result += toBase64Table[data[j] >> 2]; + result += toBase64Table[(data[j] & 0x03) << 4]; + result += toBase64Table[64]; + result += toBase64Table[64]; } return result; diff --git a/include/display.js b/include/display.js index 04b5d3f6..b9df4571 100644 --- a/include/display.js +++ b/include/display.js @@ -502,8 +502,8 @@ that.finishTile = function() { // else: No-op, if not prefer_js then already done by setSubTile }; -rgbImageData = function(x, y, width, height, arr, offset) { - var img, i, j, data, v = viewport; +rgbImageData = function(x, y, vx, vy, width, height, arr, offset) { + var img, i, j, data; /* if ((x - v.x >= v.w) || (y - v.y >= v.h) || (x - v.x + width < 0) || (y - v.y + height < 0)) { @@ -519,11 +519,11 @@ rgbImageData = function(x, y, width, height, arr, offset) { data[i + 2] = arr[j + 2]; data[i + 3] = 255; // Set Alpha } - c_ctx.putImageData(img, x - v.x, y - v.y); + c_ctx.putImageData(img, x - vx, y - vy); }; -bgrxImageData = function(x, y, width, height, arr, offset) { - var img, i, j, data, v = viewport; +bgrxImageData = function(x, y, vx, vy, width, height, arr, offset) { + var img, i, j, data; /* if ((x - v.x >= v.w) || (y - v.y >= v.h) || (x - v.x + width < 0) || (y - v.y + height < 0)) { @@ -539,10 +539,10 @@ bgrxImageData = function(x, y, width, height, arr, offset) { data[i + 2] = arr[j ]; data[i + 3] = 255; // Set Alpha } - c_ctx.putImageData(img, x - v.x, y - v.y); + c_ctx.putImageData(img, x - vx, y - vy); }; -cmapImageData = function(x, y, width, height, arr, offset) { +cmapImageData = function(x, y, vx, vy, width, height, arr, offset) { var img, i, j, data, bgr, cmap; img = c_ctx.createImageData(width, height); data = img.data; @@ -554,23 +554,23 @@ cmapImageData = function(x, y, width, height, arr, offset) { data[i + 2] = bgr[0]; data[i + 3] = 255; // Set Alpha } - c_ctx.putImageData(img, x - viewport.x, y - viewport.y); + c_ctx.putImageData(img, x - vx, y - vy); }; that.blitImage = function(x, y, width, height, arr, offset) { if (conf.true_color) { - bgrxImageData(x, y, width, height, arr, offset); + bgrxImageData(x, y, viewport.x, viewport.y, width, height, arr, offset); } else { - cmapImageData(x, y, width, height, arr, offset); + cmapImageData(x, y, viewport.x, viewport.y, width, height, arr, offset); } }; that.blitRgbImage = function(x, y, width, height, arr, offset) { if (conf.true_color) { - rgbImageData(x, y, width, height, arr, offset); + rgbImageData(x, y, viewport.x, viewport.y, width, height, arr, offset); } else { // prolly wrong... - cmapImageData(x, y, width, height, arr, offset); + cmapImageData(x, y, viewport.x, viewport.y, width, height, arr, offset); } }; diff --git a/include/jsunzip.js b/include/jsunzip.js index f815218f..8968f866 100755 --- a/include/jsunzip.js +++ b/include/jsunzip.js @@ -352,20 +352,28 @@ this.getbit = function(d) } /* read a num bit value from a stream and add base */ +function read_bits_direct(source, bitcount, tag, idx, num) +{ + var val = 0; + while (bitcount < 24) { + tag = tag | (source[idx++] & 0xff) << bitcount; + bitcount += 8; + } + val = tag & (0xffff >> (16 - num)); + tag >>= num; + bitcount -= num; + return [bitcount, tag, idx, val]; +} this.read_bits = function(d, num, base) { if (!num) return base; - var val = 0; - while (d.bitcount < 24) { - d.tag = d.tag | (d.source[d.sourceIndex++] & 0xff) << d.bitcount; - d.bitcount += 8; - } - val = d.tag & (0xffff >> (16 - num)); - d.tag >>= num; - d.bitcount -= num; - return val + base; + var ret = read_bits_direct(d.source, d.bitcount, d.tag, d.sourceIndex, num); + d.bitcount = ret[0]; + d.tag = ret[1]; + d.sourceIndex = ret[2]; + return ret[3] + base; } /* given a data stream and a tree, decode a symbol */ diff --git a/include/rfb.js b/include/rfb.js index f739574e..2110b7af 100644 --- a/include/rfb.js +++ b/include/rfb.js @@ -1361,6 +1361,45 @@ function display_tight(isTightPNG) { return uncompressed.data; } + var indexedToRGB = function (data, numColors, palette, width, height) { + // Convert indexed (palette based) image data to RGB + // TODO: reduce number of calculations inside loop + var dest = []; + var x, y, b, w, w1, dp, sp; + if (numColors === 2) { + w = Math.floor((width + 7) / 8); + w1 = Math.floor(width / 8); + for (y = 0; y < height; y++) { + for (x = 0; x < w1; x++) { + for (b = 7; b >= 0; b--) { + dp = (y*width + x*8 + 7-b) * 3; + sp = (data[y*w + x] >> b & 1) * 3; + dest[dp ] = palette[sp ]; + dest[dp+1] = palette[sp+1]; + dest[dp+2] = palette[sp+2]; + } + } + for (b = 7; b >= 8 - width % 8; b--) { + dp = (y*width + x*8 + 7-b) * 3; + sp = (data[y*w + x] >> b & 1) * 3; + dest[dp ] = palette[sp ]; + dest[dp+1] = palette[sp+1]; + dest[dp+2] = palette[sp+2]; + } + } + } else { + for (y = 0; y < height; y++) { + for (x = 0; x < width; x++) { + dp = (y*width + x) * 3; + sp = data[y*width + x] * 3; + dest[dp ] = palette[sp ]; + dest[dp+1] = palette[sp+1]; + dest[dp+2] = palette[sp+2]; + } + } + } + return dest; + }; var handlePalette = function() { var numColors = rQ[rQi + 2] + 1; var paletteSize = numColors * fb_depth; @@ -1392,45 +1431,12 @@ function display_tight(isTightPNG) { } // Convert indexed (palette based) image data to RGB - // TODO: reduce number of calculations inside loop - var dest = []; - var x, y, b, w, w1, dp, sp; - if (numColors === 2) { - w = Math.floor((FBU.width + 7) / 8); - w1 = Math.floor(FBU.width / 8); - for (y = 0; y < FBU.height; y++) { - for (x = 0; x < w1; x++) { - for (b = 7; b >= 0; b--) { - dp = (y*FBU.width + x*8 + 7-b) * 3; - sp = (data[y*w + x] >> b & 1) * 3; - dest[dp ] = palette[sp ]; - dest[dp+1] = palette[sp+1]; - dest[dp+2] = palette[sp+2]; - } - } - for (b = 7; b >= 8 - FBU.width % 8; b--) { - dp = (y*FBU.width + x*8 + 7-b) * 3; - sp = (data[y*w + x] >> b & 1) * 3; - dest[dp ] = palette[sp ]; - dest[dp+1] = palette[sp+1]; - dest[dp+2] = palette[sp+2]; - } - } - } else { - for (y = 0; y < FBU.height; y++) { - for (x = 0; x < FBU.width; x++) { - dp = (y*FBU.width + x) * 3; - sp = data[y*FBU.width + x] * 3; - dest[dp ] = palette[sp ]; - dest[dp+1] = palette[sp+1]; - dest[dp+2] = palette[sp+2]; - } - } - } + var rgb = indexedToRGB(data, numColors, palette, FBU.width, FBU.height); + // Add it to the render queue display.renderQ_push({ 'type': 'blitRgb', - 'data': dest, + 'data': rgb, 'x': FBU.x, 'y': FBU.y, 'width': FBU.width,