var decompress = function(data, w, h, bpl, cdata){ var cdoff = 0; /* cdata offset */ var doff = 0; /* data offset */ var odoff = 0; /* offset data offset */ var c, cnt; var offs, offlen; for(;;){ if(doff >= data.length){ return cdoff; } if(cdoff >= cdata.length){ throw("buffer too small"); } c = cdata[cdoff++]; if(c >= 128){ for(cnt = c-128+1; cnt > 0; --cnt){ data[doff++] = cdata[cdoff++]; } }else{ offs = cdata[cdoff++] + ((c&3)<<8)+1; odoff = doff - offs; for(cnt = (c>>2) + 3; cnt > 0; --cnt){ data[doff++] = data[odoff++]; } } } } var bytesperline = function(w, depth){ var bytesperpix = Math.ceil(depth / 8); var pixperbyte = Math.floor(8 / depth); if(depth < 8){ return Math.ceil(w / pixperbyte); }else{ return w * bytesperpix; } } var getpixel = function(data, depth, w, h, line, col){ var bytesperpix = Math.ceil(depth / 8); var pixperbyte = Math.floor(8 / depth); var bytesperline = Math.ceil((w * pixperbyte) / 8); var pixordinbyte = col % pixperbyte; if(depth < 8){ bytesperline = Math.ceil(w / pixperbyte); var offset = (line * bytesperline) + Math.floor((col * pixperbyte) / 8); }else{ bytesperline = w * bytesperpix; var offset = (line * bytesperline) + (col * bytesperpix); } if(line > h){ throw("pixel line index out of bounds"); } if(col > w){ throw("pixel column index out of bounds"); } if(depth < 8){ /* XXX remember to shift the whole mess back down! */ var mask = (1 << depth) - 1; return (data[offset] >> (depth * pixordinbyte)) & mask; }else{ /* XXX THIS IS WRONG! */ /* possibly: for(var i = bpp; i > 0; --i) */ var pixel = 0; for(var i = 0; i < bytesperpix; ++i){ pixel |= data[offset + i] << (8 * i); } return pixel; } } var canvaspos = function(w, h, line, col){ return ((line * w) + col) * 4; } var scalepixel = function(pixel, from, to){ if(from < to){ return Math.floor((pixel * ((1<> (from - to); } } var loader = { generic: function(arr, w, h, chan, data){ var depth = Chan.chantodepth(chan); for(var line = 0; line < h; ++line){ for(var col = 0; col < w; ++col){ var pixel = getpixel(data, depth, w, h, line, col); var cp = canvaspos(w, h, line, col); arr[cp + 3] = 0xFF; /* Default to 100% alpha. */ for(var c = chan; c; c >>= 8){ var nbits = Chan.NBITS(c); var px = pixel & ((1<>= nbits; } } } return arr; }, grey: function(canvas, w, h, chan, data){ if((Chan.TYPE(chan) != Chan.chans.CGrey) || (chan >> 8)){ throw("not a grey-only image"); } var depth = Chan.NBITS(chan); var pixperbyte = Math.floor(8 / depth); var bytesperline = Math.ceil(w / pixperbyte); var cp = 0; /* canvas offset */ var dp = 0; /* data offset */ for(var line = 0; line < h; ++line, dp += bytesperline){ for(var b = 0; b < bytesperline; ++b){ for(var p = 1; p <= pixperbyte; ++p){ if((b * pixperbyte) + p > w) break; var px = (data[dp + b] >> ((pixperbyte - p) * depth)) & ((1<> 16) & 0xFF; canvas[cp++] = (px >> 8) & 0xFF; canvas[cp++] = (px >> 0) & 0xFF; canvas[cp++] = 0xFF; } } } } Memdraw.Load = function(canvas, w, h, chan, data, iscompressed){ var depth = Chan.chantodepth(chan); var bpl = Math.ceil((w * depth) / 8); var len; if(iscompressed){ var cdata = data; data = new Uint8Array(h * bpl); len = decompress(data, w, h, bpl, cdata); }else{ len = bpl * h; } if(!(chan>>8)){ switch(Chan.TYPE(chan)){ case Chan.chans.CGrey: loader.grey(canvas, w, h, chan, data); return len; case Chan.chans.CMap: if(Chan.NBITS(chan) == 8){ loader.cmap8(canvas, w, h, chan, data); return len; } } } loader.generic(canvas, w, h, chan, data); return len; }