From 3c2a0f11b1f63595d08458f31e4c21738cd4ca5d Mon Sep 17 00:00:00 2001
From: Brendan Dahl <brendan.dahl@gmail.com>
Date: Tue, 3 Jan 2012 14:26:19 -0800
Subject: [PATCH 1/3] Decode more jpegs using the browser if possible.

---
 src/evaluator.js |  3 ++-
 src/image.js     |  2 +-
 src/stream.js    | 53 ++++++++++++++++++++++++++++++------------------
 3 files changed, 36 insertions(+), 22 deletions(-)

diff --git a/src/evaluator.js b/src/evaluator.js
index 2905565da..3daf97da9 100644
--- a/src/evaluator.js
+++ b/src/evaluator.js
@@ -211,7 +211,8 @@ var PartialEvaluator = (function PartialEvaluatorClosure() {
         args = [objId, w, h];
 
         var softMask = dict.get('SMask', 'IM') || false;
-        if (!softMask && image instanceof JpegStream && image.isNative) {
+        if (!softMask && image instanceof JpegStream &&
+            image.isNativelySupported(xref, resources)) {
           // These JPEGs don't need any more processing so we can just send it.
           fn = 'paintJpegXObject';
           handler.send('obj', [objId, 'JpegStream', image.getIR()]);
diff --git a/src/image.js b/src/image.js
index 29bad4d8a..6e7ab2020 100644
--- a/src/image.js
+++ b/src/image.js
@@ -9,7 +9,7 @@ var PDFImage = (function PDFImageClosure() {
    * when the image data is ready.
    */
   function handleImageData(handler, xref, res, image, promise) {
-    if (image instanceof JpegStream && image.isNative) {
+    if (image instanceof JpegStream && image.isNativelyDecodable(xref, res)) {
       // For natively supported jpegs send them to the main thread for decoding.
       var dict = image.dict;
       var colorSpace = dict.get('ColorSpace', 'CS');
diff --git a/src/stream.js b/src/stream.js
index d996f5c91..3367636b4 100644
--- a/src/stream.js
+++ b/src/stream.js
@@ -803,35 +803,23 @@ var JpegStream = (function JpegStreamClosure() {
     // need to be removed
     this.dict = dict;
 
-    // Flag indicating wether the image can be natively loaded.
-    this.isNative = true;
-
-    this.colorTransform = -1;
+    this.colorTransform = dict.get('ColorTransform') || -1;
+    this.isAdobeImage = false;
 
     if (isAdobeImage(bytes)) {
-      // when bug 674619 land, let's check if browser can do
-      // normal cmyk and then we won't have to the following
-      var cs = xref.fetchIfRef(dict.get('ColorSpace'));
-
-      // DeviceRGB and DeviceGray are the only Adobe images that work natively
-      if (isName(cs) && (cs.name === 'DeviceRGB' || cs.name === 'DeviceGray')) {
-        bytes = fixAdobeImage(bytes);
-        this.src = bytesToString(bytes);
-      } else {
-        this.colorTransform = dict.get('ColorTransform');
-        this.isNative = false;
-        this.bytes = bytes;
-      }
-    } else {
-      this.src = bytesToString(bytes);
+      this.isAdobeImage = true;
+      bytes = fixAdobeImage(bytes);
     }
 
+    this.bytes = bytes;
+
     DecodeStream.call(this);
   }
 
   JpegStream.prototype = Object.create(DecodeStream.prototype);
 
   JpegStream.prototype.ensureBuffer = function jpegStreamEnsureBuffer(req) {
+    // todo make sure this isn't called on natively supported jpegs
     if (this.bufferLength)
       return;
     var jpegImage = new JpegImage();
@@ -844,11 +832,36 @@ var JpegStream = (function JpegStreamClosure() {
     this.bufferLength = data.length;
   };
   JpegStream.prototype.getIR = function jpegStreamGetIR() {
-    return this.src;
+    return bytesToString(this.bytes);
   };
   JpegStream.prototype.getChar = function jpegStreamGetChar() {
       error('internal error: getChar is not valid on JpegStream');
   };
+  /**
+   * Checks if the image can be decoded and displayed by the browser without any
+   * further processing such as color space conversions.
+   */
+  JpegStream.prototype.isNativelySupported = function isNativelySupported(xref,
+                                                                          res) {
+    var cs = ColorSpace.parse(this.dict.get('ColorSpace'), xref, res);
+    if (cs.name === 'DeviceGray' || cs.name === 'DeviceRGB')
+      return true;
+    if (cs.name === 'DeviceCMYK' && !this.isAdobeImage &&
+        this.colorTransform < 1)
+      return true;
+    return false;
+  };
+  /**
+   * Checks if the image can be decoded by the browser.
+   */
+  JpegStream.prototype.isNativelyDecodable = function isNativelyDecodable(xref,
+                                                                          res) {
+    var cs = ColorSpace.parse(this.dict.get('ColorSpace'), xref, res);
+    if (cs.numComps == 1 || cs.numComps == 3)
+      return true;
+
+    return false;
+  };
 
   return JpegStream;
 })();

From 9538da2b588963ac4c9148de0ec551e32969334c Mon Sep 17 00:00:00 2001
From: Brendan Dahl <brendan.dahl@gmail.com>
Date: Wed, 4 Jan 2012 11:56:53 -0800
Subject: [PATCH 2/3] Move comments.

---
 src/stream.js | 3 ++-
 1 file changed, 2 insertions(+), 1 deletion(-)

diff --git a/src/stream.js b/src/stream.js
index 3367636b4..2c45d32a1 100644
--- a/src/stream.js
+++ b/src/stream.js
@@ -819,7 +819,6 @@ var JpegStream = (function JpegStreamClosure() {
   JpegStream.prototype = Object.create(DecodeStream.prototype);
 
   JpegStream.prototype.ensureBuffer = function jpegStreamEnsureBuffer(req) {
-    // todo make sure this isn't called on natively supported jpegs
     if (this.bufferLength)
       return;
     var jpegImage = new JpegImage();
@@ -844,6 +843,8 @@ var JpegStream = (function JpegStreamClosure() {
   JpegStream.prototype.isNativelySupported = function isNativelySupported(xref,
                                                                           res) {
     var cs = ColorSpace.parse(this.dict.get('ColorSpace'), xref, res);
+    // when bug 674619 lands, let's check if browser can do
+    // normal cmyk and then we won't need to decode in JS
     if (cs.name === 'DeviceGray' || cs.name === 'DeviceRGB')
       return true;
     if (cs.name === 'DeviceCMYK' && !this.isAdobeImage &&

From 7bf5daa273f57f91daa88ca30c4b96a6e51ef834 Mon Sep 17 00:00:00 2001
From: Brendan Dahl <brendan.dahl@gmail.com>
Date: Thu, 5 Jan 2012 11:06:17 -0800
Subject: [PATCH 3/3] Only set transform when its a non default.

---
 src/stream.js | 8 +++++---
 1 file changed, 5 insertions(+), 3 deletions(-)

diff --git a/src/stream.js b/src/stream.js
index 2c45d32a1..adefc99d5 100644
--- a/src/stream.js
+++ b/src/stream.js
@@ -803,8 +803,8 @@ var JpegStream = (function JpegStreamClosure() {
     // need to be removed
     this.dict = dict;
 
-    this.colorTransform = dict.get('ColorTransform') || -1;
     this.isAdobeImage = false;
+    this.colorTransform = dict.get('ColorTransform') || -1;
 
     if (isAdobeImage(bytes)) {
       this.isAdobeImage = true;
@@ -822,7 +822,8 @@ var JpegStream = (function JpegStreamClosure() {
     if (this.bufferLength)
       return;
     var jpegImage = new JpegImage();
-    jpegImage.colorTransform = this.colorTransform;
+    if (this.colorTransform != -1)
+      jpegImage.colorTransform = this.colorTransform;
     jpegImage.parse(this.bytes);
     var width = jpegImage.width;
     var height = jpegImage.height;
@@ -858,7 +859,8 @@ var JpegStream = (function JpegStreamClosure() {
   JpegStream.prototype.isNativelyDecodable = function isNativelyDecodable(xref,
                                                                           res) {
     var cs = ColorSpace.parse(this.dict.get('ColorSpace'), xref, res);
-    if (cs.numComps == 1 || cs.numComps == 3)
+    var numComps = cs.numComps;
+    if (numComps == 1 || numComps == 3)
       return true;
 
     return false;