[Pkg-javascript-commits] [pdf.js] 38/141: Read color info from JPX stream

David Prévot taffit at moszumanska.debian.org
Sat Apr 19 22:40:28 UTC 2014


This is an automated email from the git hooks/post-receive script.

taffit pushed a commit to branch master
in repository pdf.js.

commit 1ccc8a64b7beeb79f5dc4aee1a03ef04f23997ee
Author: fkaelberer <o_0_o at gmx.de>
Date:   Sat Apr 5 17:27:18 2014 +0200

    Read color info from JPX stream
    
    Fix colors problem #4540 + minor cleanup
    
    fix lint warnings
---
 src/core/image.js | 38 ++++++++++++++++-------
 src/core/jpx.js   | 91 +++++++++++++++++++++++++++++++++++++------------------
 2 files changed, 89 insertions(+), 40 deletions(-)

diff --git a/src/core/image.js b/src/core/image.js
index 8dc7b6d..17ea6b6 100644
--- a/src/core/image.js
+++ b/src/core/image.js
@@ -14,8 +14,8 @@
  * See the License for the specific language governing permissions and
  * limitations under the License.
  */
-/* globals ColorSpace, DecodeStream, error, isArray, ImageKind, isStream,
-           JpegStream, Name, Promise, Stream, warn, LegacyPromise */
+/* globals ColorSpace, DecodeStream, error, info, isArray, ImageKind, isStream,
+           JpegStream, JpxImage, Name, Promise, Stream, warn, LegacyPromise */
 
 'use strict';
 
@@ -51,16 +51,21 @@ var PDFImage = (function PDFImageClosure() {
   }
   function PDFImage(xref, res, image, inline, smask, mask, isMask) {
     this.image = image;
-    if (image.getParams) {
-      // JPX/JPEG2000 streams directly contain bits per component
-      // and color space mode information.
-      warn('get params from actual stream');
-      // var bits = ...
-      // var colorspace = ...
+    var dict = image.dict;
+    if (dict.get('Filter').name === 'JPXDecode') {
+      info('get image params from JPX stream');
+      var jpxImage = new JpxImage();
+      var data = image.stream.bytes;
+      jpxImage.parseImageProperties(data, 0, data.length);
+      image.bitsPerComponent = jpxImage.bitsPerComponent;
+      image.numComps = jpxImage.componentsCount;
+    }
+    if (dict.get('Filter').name === 'JBIG2Decode') {
+      image.bitsPerComponent = 1;
+      image.numComps = 1;
     }
     // TODO cache rendered images?
 
-    var dict = image.dict;
     this.width = dict.get('Width', 'W');
     this.height = dict.get('Height', 'H');
 
@@ -89,8 +94,19 @@ var PDFImage = (function PDFImageClosure() {
     if (!this.imageMask) {
       var colorSpace = dict.get('ColorSpace', 'CS');
       if (!colorSpace) {
-        warn('JPX images (which do not require color spaces)');
-        colorSpace = Name.get('DeviceRGB');
+        info('JPX images (which do not require color spaces)');
+        switch (image.numComps) {
+          case 1:
+            colorSpace = Name.get('DeviceGray');
+            break;
+          case 3:
+            colorSpace = Name.get('DeviceRGB');
+            break;
+          default:
+            // TODO: Find out how four color channels are handled. CMYK? Alpha?
+            error('JPX images with ' + this.numComps +
+                  ' color components not supported.');
+        }
       }
       this.colorSpace = ColorSpace.parse(colorSpace, xref, res);
       this.numComps = this.colorSpace.numComps;
diff --git a/src/core/jpx.js b/src/core/jpx.js
index 55d4078..de8cc90 100644
--- a/src/core/jpx.js
+++ b/src/core/jpx.js
@@ -26,10 +26,6 @@ var JpxImage = (function JpxImageClosure() {
     'HL': 1,
     'HH': 2
   };
-  var TransformType = {
-    IRREVERSIBLE: 0,
-    REVERSIBLE: 1
-  };
   function JpxImage() {
     this.failOnCorruptedImage = false;
   }
@@ -102,6 +98,37 @@ var JpxImage = (function JpxImageClosure() {
         }
       }
     },
+    parseImageProperties: function JpxImage_parseImageProperties(data, start,
+                                                                 end) {
+      try {
+        var position = start;
+        while (position + 40 < end) {
+          var code = readUint16(data, position);
+          // Image and tile size (SIZ)
+          if (code == 0xFF51) {
+            var Xsiz = readUint32(data, position + 6);
+            var Ysiz = readUint32(data, position + 10);
+            var XOsiz = readUint32(data, position + 14);
+            var YOsiz = readUint32(data, position + 18);
+            var Csiz = readUint16(data, position + 38);
+            this.width = Xsiz - XOsiz;
+            this.height = Ysiz - YOsiz;
+            this.componentsCount = Csiz;
+            // Results are always returned as UInt8Arrays 
+            this.bitsPerComponent = 8;
+            return;
+          }
+          position += 1;
+        }
+        throw 'No size marker found in JPX stream';
+      } catch (e) {
+        if (this.failOnCorruptedImage) {
+          error('JPX error: ' + e);
+        } else {
+          warn('JPX error: ' + e + '. Trying to recover');
+        }
+      }
+    },
     parseCodestream: function JpxImage_parseCodestream(data, start, end) {
       var context = {};
       try {
@@ -270,7 +297,7 @@ var JpxImage = (function JpxImageClosure() {
               cod.verticalyStripe = !!(blockStyle & 8);
               cod.predictableTermination = !!(blockStyle & 16);
               cod.segmentationSymbolUsed = !!(blockStyle & 32);
-              cod.transformation = data[j++];
+              cod.reversibleTransformation = data[j++];
               if (cod.entropyCoderWithCustomPrecincts) {
                 var precinctsSizes = [];
                 while (j < length + position) {
@@ -333,6 +360,8 @@ var JpxImage = (function JpxImageClosure() {
               length = readUint16(data, position);
               // skipping content
               break;
+            case 0xFF53: // Coding style component (COC)
+              throw 'Codestream code 0xFF53 (COC) is not implemented';
             default:
               throw 'Unknown codestream code: ' + code.toString(16);
           }
@@ -878,7 +907,7 @@ var JpxImage = (function JpxImageClosure() {
     return position;
   }
   function copyCoefficients(coefficients, x0, y0, width, height,
-                            delta, mb, codeblocks, transformation,
+                            delta, mb, codeblocks, reversible,
                             segmentationSymbolUsed) {
     for (var i = 0, ii = codeblocks.length; i < ii; ++i) {
       var codeblock = codeblocks[i];
@@ -934,16 +963,22 @@ var JpxImage = (function JpxImageClosure() {
 
       var offset = (codeblock.tbx0_ - x0) + (codeblock.tby0_ - y0) * width;
       var n, nb, correction, position = 0;
-      var irreversible = (transformation === TransformType.IRREVERSIBLE);
+      var irreversible = !reversible;
       var sign = bitModel.coefficentsSign;
       var magnitude = bitModel.coefficentsMagnitude;
       var bitsDecoded = bitModel.bitsDecoded;
+      var magnitudeCorrection = reversible ? 0 : 0.5;
       for (var j = 0; j < blockHeight; j++) {
         for (var k = 0; k < blockWidth; k++) {
-          n = (sign[position] ? -1 : 1) * magnitude[position];
-          nb = bitsDecoded[position];
-          correction = (irreversible || mb > nb) ? 1 << (mb - nb) : 1;
-          coefficients[offset++] = n * correction * delta;
+          var mag = magnitude[position];
+          if (mag !== 0) {
+            n = sign[position] ? -(mag + magnitudeCorrection) :
+                                  (mag + magnitudeCorrection);
+            nb = bitsDecoded[position];
+            correction = (irreversible || mb > nb) ? 1 << (mb - nb) : 1;
+            coefficients[offset] = n * correction * delta;
+          }
+          offset++;
           position++;
         }
         offset += width - blockWidth;
@@ -959,16 +994,15 @@ var JpxImage = (function JpxImageClosure() {
     var spqcds = quantizationParameters.SPqcds;
     var scalarExpounded = quantizationParameters.scalarExpounded;
     var guardBits = quantizationParameters.guardBits;
-    var transformation = codingStyleParameters.transformation;
     var segmentationSymbolUsed = codingStyleParameters.segmentationSymbolUsed;
     var precision = context.components[c].precision;
 
-    var transformation = codingStyleParameters.transformation;
-    var transform = (transformation === TransformType.IRREVERSIBLE ?
-                     new IrreversibleTransform() : new ReversibleTransform());
+    var reversible = codingStyleParameters.reversibleTransformation;
+    var transform = (reversible ? new ReversibleTransform() :
+                                  new IrreversibleTransform());
 
     var subbandCoefficients = [];
-    var k = 0, b = 0;
+    var b = 0;
     for (var i = 0; i <= decompositionLevelsCount; i++) {
       var resolution = component.resolutions[i];
 
@@ -989,13 +1023,13 @@ var JpxImage = (function JpxImageClosure() {
         var gainLog2 = SubbandsGainLog2[subband.type];
 
         // calulate quantization coefficient (Section E.1.1.1)
-        var delta = (transformation === TransformType.IRREVERSIBLE ?
-          Math.pow(2, precision + gainLog2 - epsilon) * (1 + mu / 2048) : 1);
+        var delta = (reversible ? 1 :
+          Math.pow(2, precision + gainLog2 - epsilon) * (1 + mu / 2048));
         var mb = (guardBits + epsilon - 1);
 
         var coefficients = new Float32Array(width * height);
         copyCoefficients(coefficients, subband.tbx0, subband.tby0,
-          width, height, delta, mb, subband.codeblocks, transformation,
+          width, height, delta, mb, subband.codeblocks, reversible,
           segmentationSymbolUsed);
 
         subbandCoefficients.push({
@@ -1034,8 +1068,7 @@ var JpxImage = (function JpxImageClosure() {
       // Section G.2.2 Inverse multi component transform
       if (tile.codingStyleDefaultParameters.multipleComponentTransform) {
         var component0 = tile.components[0];
-        var transformation = component0.codingStyleParameters.transformation;
-        if (transformation === TransformType.IRREVERSIBLE) {
+        if (!component0.codingStyleParameters.reversibleTransformation) {
           // inverse irreversible multiple component transform
           var y0items = result[0].items;
           var y1items = result[1].items;
@@ -1628,26 +1661,26 @@ var JpxImage = (function JpxImageClosure() {
       var items = new Float32Array(width * height);
       var i, j, k, l;
 
-      for (i = 0; i < llHeight; i++) {
-        var k = i * llWidth, l = i * 2 * width;
+      for (i = 0, k = 0; i < llHeight; i++) {
+        l = i * 2 * width;
         for (var j = 0; j < llWidth; j++, k++, l += 2) {
           items[l] = llItems[k];
         }
       }
-      for (i = 0; i < hlHeight; i++) {
-        k = i * hlWidth; l = i * 2 * width + 1;
+      for (i = 0, k = 0; i < hlHeight; i++) {
+        l = i * 2 * width + 1;
         for (j = 0; j < hlWidth; j++, k++, l += 2) {
           items[l] = hlItems[k];
         }
       }
-      for (i = 0; i < lhHeight; i++) {
-        k = i * lhWidth; l = (i * 2 + 1) * width;
+      for (i = 0, k = 0; i < lhHeight; i++) {
+        l = (i * 2 + 1) * width;
         for (j = 0; j < lhWidth; j++, k++, l += 2) {
           items[l] = lhItems[k];
         }
       }
-      for (i = 0; i < hhHeight; i++) {
-        k = i * hhWidth; l = (i * 2 + 1) * width + 1;
+      for (i = 0, k = 0; i < hhHeight; i++) {
+        l = (i * 2 + 1) * width + 1;
         for (j = 0; j < hhWidth; j++, k++, l += 2) {
           items[l] = hhItems[k];
         }

-- 
Alioth's /usr/local/bin/git-commit-notice on /srv/git.debian.org/git/pkg-javascript/pdf.js.git



More information about the Pkg-javascript-commits mailing list