From: sbarman Date: Tue, 21 Jun 2011 00:51:38 +0000 (-0700) Subject: Merge branch 'master' into predictor X-Git-Url: https://git.parisson.com/?a=commitdiff_plain;h=ce9229c113eb06b59c2d548f50a147b2c742f05d;p=pdf.js.git Merge branch 'master' into predictor Conflicts: pdf.js --- ce9229c113eb06b59c2d548f50a147b2c742f05d diff --cc pdf.js index e086b82,4004430..488db9a --- a/pdf.js +++ b/pdf.js @@@ -509,224 -525,69 +526,273 @@@ var FlateStream = (function() return constructor; })(); - ++/* +var FilterPredictor = (function() { + function constructor(str, type, width, colors, bits) { + this.str = str; + this.dict = str.dict; + + this.type = type; + this.width = width; + this.colors = colors; + this.bits = bits; + + this.nVals = width * colors; + var pixBytes = (colors * bits + 7) >> 3; + this.pixBytes = pixBytes; + var rowBytes = ((width * colors * bits + 7) >> 3) + pixBytes; + this.rowBytes = rowBytes; + + if (width < 0 || colors < 0 || bits < 0 ||bits > 16) + error("Invalid predictor"); + + var prevLine = []; + for (var i = 0; i < rowBytes; ++i) + prevLine.push(0); + this.prevLine = prevLine; + this.prevIdx = rowBytes; + } + + constructor.prototype = { + getByte: function() { + if (this.prevIdx >= this.rowBytes) { + if(!this.getNextLine()) + return; + } + return this.prevLine[this.prevIdx++]; + }, + getBytes: function(length) { + var buf = new Uint8Array(length); + for (var i = 0; i < length; ++i) + buf[i] = this.getByte(); + return buf; + }, + getNextLine: function() { + if (this.type >= 10) { + var curType = this.str.getByte(); + if (!curType) + return; + curType += 10; + } else { + var curType = this.type; + } + + var line = []; + for (var i = 0; i < this.rowBytes - this.pixBytes; i++) + line.push(this.str.getByte()); + + var pixBytes = this.pixBytes; + var rowBytes = this.rowBytes; + var prevLine = this.prevLine; + + var upLeftBuf = []; + for (var i = 0, ii = pixBytes + 1; i < ii; ++i) + upLeftBuf.push(0); + + for (var i = pixBytes, ii = rowBytes + pixBytes + 1; i < ii; ++i) { + for (var j = pixBytes; j > 0; --j) { + upLeftBuf[j] = upLeftBuf[j - 1]; + } + upLeftBuf[0] = prevLine[i]; + + var c = line[i - pixBytes]; + if (c == undefined) { + if (i > pixBytes) + break; + return; + } + switch (curType) { + case 11: + prevLine[i] = prevLine[i - pixBytes] + c; + break; + case 12: + prevLine[i] = prevLine[i] + c; + break; + case 13: + prevLine[i] = ((prevLine[i - pixBytes] + + prevLine[i]) >> 1) + c; + break; + case 14: + var left = prevLine[i - pixBytes]; + var up = prevLine[i]; + var upLeft = upLeftBuf[pixBytes]; + var p = left + up - upLeft; + + var pa = p - left; + if (pa < 0) + pa = -pa; + var pb = p - up; + if (pb < 0) + pb = -pb; + var pc = p - upLeft; + if (pc < 0) + pc = -pc; + + if (pa <= pb && pa <= pc) + prevLine[i] = left + c; + else if (pb <= pc) + prevLine[i] = up + c; + else + prevLine[i] = upLeft + c; + break; + case 10: + default: + prevLine[i] = c; + break; + } + } + var bits = this.bits; + var colors = this.colors; + if (curType === 2) { + if (bits === 1) { + var inbuf = prevLine[pixBytes - 1]; + for (var i = pixBytes; i < rowBytes; i+= 8) { + inBuf = (inBuf << 8) | prevLine[i]; + prevLine[i] ^= inBuf >> colors; + } + } else if (bits === 8) { + for (var i = pixBytes; i < rowBytes; ++i) + prevLine[i] += prevLine[i - colors]; + } else { + for (var i = 0, ii = colors + 1; i < ii; ++i) + upLeftBuf[i] = 0; + var bitMask = (1 << bits) - 1; + var inbuf = 0, outbut = 0; + var inbits = 0, outbits = 0; + var j = pixBytes, k = pixBytes; + var width = this.width; + for (var i = 0; i < width; ++i) { + for (var kk = 0; kk < colors; ++kk) { + if (inbits < bits) { + inbuf = (inbuf << 8) | (prevLine[j++] & 255); + inbits += 8; + } + upLeftBuf[kk] = (upLeftBuf[kk] + (inbuf >> + (inbits - bits))) & bitMask; + inbits -= bits; + outbuf = (outbuf << bits) | upLeftBuf[kk]; + outbits += bits; + if (outbits >= 8) { + prevLine[k++] = (outbuf >> (outbits - 8)); + outbits -= 8; + } + } + } + if (outbits > 0) { + prevLine[k++] = (outbuf << (8 - outbits)) + + (inbuf & ((1 << (8 - outbits)) - 1)) + } + } + } + this.prevIdx = pixBytes; + return true; + } + }; + return constructor; +})(); ++*/ + // A JpegStream can't be read directly. We use the platform to render the underlying + // JPEG data for us. + var JpegStream = (function() { + function constructor(bytes, dict) { + // TODO: per poppler, some images may have "junk" before that need to be removed + this.dict = dict; + + // create DOM image + var img = new Image(); + img.src = "data:image/jpeg;base64," + window.btoa(bytesToString(bytes)); + this.domImage = img; + } + + constructor.prototype = { ++ getByte: function() { ++ // dummy method to pass IsStream test ++ error("shouldnt be called"); ++ }, + getImage: function() { + return this.domImage; + } + }; + + return constructor; + })(); + var PredictorStream = (function() { function constructor(stream, params) { - this.stream = stream; - this.predictor = params.get("Predictor") || 1; - if (this.predictor <= 1) { ++ var predictor = params.get("Predictor") || 1; ++ this.predictor = predictor; ++ ++ if (predictor <= 1) + return stream; // no prediction - } ++ if (predictor !== 2 && (predictor < 10 || predictor > 15)) ++ error("Unsupported predictor"); ++ ++ if (predictor === 2) ++ this.readRow = this.readRowTiff; ++ else ++ this.readRow = this.readRowPng; ++ + this.stream = stream; + this.dict = stream.dict; - this.predictor = params.get("Predictor") || 1; - if (this.predictor <= 1) { - return stream; // no prediction - } if (params.has("EarlyChange")) { error("EarlyChange predictor parameter is not supported"); } -- this.colors = params.get("Colors") || 1; -- this.bitsPerComponent = params.get("BitsPerComponent") || 8; -- this.columns = params.get("Columns") || 1; - if (this.bitsPerComponent !== 8) { - error("Multi-byte predictors are not supported"); - if (this.colors !== 1 || this.bitsPerComponent !== 8) { - error("Multi-color and multi-byte predictors are not supported"); -- } -- if (this.predictor < 10 || this.predictor > 15) { -- error("Unsupported predictor"); -- } - this.currentRow = new Uint8Array(this.columns * this.colors); - this.currentRow = new Uint8Array(this.columns); -- this.pos = 0; -- this.bufferLength = 0; ++ var colors = params.get("Colors") || 1; ++ this.colors = colors; ++ var bits = params.get("BitsPerComponent") || 8; ++ this.bits = bits; ++ var columns = params.get("Columns") || 1; ++ this.columns = columns; ++ ++ var pixBytes = (colors * bits + 7) >> 3; ++ this.pixBytes = pixBytes; ++ // add an extra pixByte to represent the pixel left column 0 ++ var rowBytes = ((columns * colors * bits + 7) >> 3) + pixBytes; ++ this.rowBytes = rowBytes; ++ ++ this.currentRow = new Uint8Array(rowBytes); ++ this.pos = rowBytes; } constructor.prototype = { -- readRow : function() { -- var lastRow = this.currentRow; - var colors = this.colors; ++ readRowTiff : function() { ++ }, ++ readRowPng : function() { ++ // swap the buffers ++ var currentRow = this.currentRow; ++ ++ var rowBytes = this.rowBytes; ++ var pixBytes = this.pixBytes; ++ var predictor = this.stream.getByte(); - var currentRow = this.stream.getBytes(this.columns * colors), i; - var currentRow = this.stream.getBytes(this.columns), i; ++ var rawBytes = this.stream.getBytes(rowBytes - pixBytes); ++ var i; ++ switch (predictor) { -- default: -- error("Unsupported predictor"); -- break; case 0: break; + case 1: - for (i = colors; i < currentRow.length; ++i) { - currentRow[i] = (currentRow[i - colors] + currentRow[i]) & 0xFF; - } ++ for (i = pixBytes; i < rowBytes; ++i) ++ currentRow[i] = (currentRow[i - pixBytes] + rawBytes[i]) & 0xFF; + break; case 2: -- for (i = 0; i < currentRow.length; ++i) { -- currentRow[i] = (lastRow[i] + currentRow[i]) & 0xFF; - } ++ for (i = pixBytes; i < rowBytes; ++i) ++ currentRow[i] = (currentRow[i] + rawBytes[i]) & 0xFF; + break; + case 3: - for (i = 0; i < color; ++i) { - currentRow[i] = ((lastRow[i] >> 1) + currentRow[i]) & 0xFF; - } - for (; i < currentRow.length; ++i) { - currentRow[i] = (((lastRow[i] + currentRow[i]) >> 1) + currentRow[i]) & 0xFF; ++ for (i = pixBytes; i < rowBytes; ++i) ++ currentRow[i] = (((currentRow[i] + currentRow[i - pixBytes]) ++ >> 1) + rawBytes[i]) & 0xFF; ++ break; ++ case 4: ++ for (i = pixBytes; i < rowBytes; ++i) { ++ var left = currentRow[i - pixBytes]; ++ var up = currentRow[i]; ++ var upLeft = } ++ default: ++ error("Unsupported predictor"); break; } this.pos = 0; @@@ -1387,29 -1242,8 +1453,29 @@@ var Parser = (function() } return stream; }, - makeFilter: function(stream, name, params) { + makeFilter: function(stream, name, length, params) { if (name == "FlateDecode" || name == "Fl") { - var flateStr = new FlateStream(stream); ++/* var flateStr = new FlateStream(stream); + if (IsDict(params)) { + var predType = params.get("Predictor"); + if (predType && predType > 1) { + var colors = params.get("Colors"); + if (!colors) + colors = 1; + var bpc = params.get("BitsPerComponent"); + if (!bpc) + bpc = 8; + var cols = params.get("Columns"); + if (!cols) + cols = 1; + + log("Predictor being used"); + flateStr = new FilterPredictor(flateStr, predType, cols, + colors, bpc); + } + } + return flateStr; - /* ++*/ if (params) { return new PredictorStream(new FlateStream(stream), params); }