From 9151cc34c58e1ea7f13bdb37e55d68fb349d980e Mon Sep 17 00:00:00 2001
From: Adrian Johnson <ajohnson@redneon.com>
Date: Mon, 30 Oct 2017 19:21:41 +1030
Subject: [PATCH] Fix pdfimages with flate encoded inline images

- Remove advance strem pos to end of image code from listImage().
  getInlineImageLength() already does this.

- Always EmbedStream in getInlineImageLength() to get size of stored image.
  The type of encoding does not matter.

- Use same record EmbeddeStream code for all image types in writeImage()

- Fix some memory leaks

Bug #103446
---
 utils/ImageOutputDev.cc | 52 ++++++++++++-------------------------------------
 1 file changed, 12 insertions(+), 40 deletions(-)

diff --git a/utils/ImageOutputDev.cc b/utils/ImageOutputDev.cc
index 41bbcdb4..5cea1c48 100644
--- a/utils/ImageOutputDev.cc
+++ b/utils/ImageOutputDev.cc
@@ -292,25 +292,6 @@ void ImageOutputDev::listImage(GfxState *state, Object *ref, Stream *str,
 
   ++imgNum;
 
-  if (inlineImg) {
-    // For inline images we need to advance the stream position to the end of the image
-    // as Gfx needs to continue reading content after the image data.
-    ImageFormat format;
-    if (!colorMap || (colorMap->getNumPixelComps() == 1 && colorMap->getBits() == 1)) {
-      format = imgMonochrome;
-    } else if (colorMap->getColorSpace()->getMode() == csDeviceGray ||
-               colorMap->getColorSpace()->getMode() == csCalGray) {
-      format = imgGray;
-    } else if ((colorMap->getColorSpace()->getMode() == csDeviceRGB ||
-		colorMap->getColorSpace()->getMode() == csCalRGB ||
-		(colorMap->getColorSpace()->getMode() == csICCBased && colorMap->getNumPixelComps() == 3)) &&
-	       colorMap->getBits() > 8) {
-      format = imgRGB48;
-    } else {
-      format = imgRGB;
-    }
-    writeImageFile(NULL, format, "", str, width, height, colorMap);
-  }
 }
 
 long ImageOutputDev::getInlineImageLength(Stream *str, int width, int height,
@@ -337,16 +318,12 @@ long ImageOutputDev::getInlineImageLength(Stream *str, int width, int height,
 
   EmbedStream *embedStr = (EmbedStream *) (str->getBaseStream());
   embedStr->rewind();
-  if (str->getKind() == strDCT || str->getKind() == strCCITTFax)
-    str = str->getNextStream();
   len = 0;
-  str->reset();
-  while (str->getChar() != EOF)
+  while (embedStr->getChar() != EOF)
     len++;
 
   embedStr->restore();
 
-
   return len;
 }
 
@@ -539,19 +516,18 @@ void ImageOutputDev::writeImage(GfxState *state, Object *ref, Stream *str,
   ImageFormat format;
   EmbedStream *embedStr;
 
-  if (dumpJPEG && str->getKind() == strDCT) {
-    if (inlineImg) {
+  if (inlineImg) {
       embedStr = (EmbedStream *) (str->getBaseStream());
-      getInlineImageLength(str, width, height, colorMap); // record the strean
+      // Record the stream. This determines the size.
+      getInlineImageLength(str, width, height, colorMap);
+      // Reading the stream again will return EOF at end of recording.
       embedStr->rewind();
-    }
+  }
 
+  if (dumpJPEG && str->getKind() == strDCT) {
     // dump JPEG file
     writeRawImage(str, "jpg");
 
-    if (inlineImg)
-      embedStr->restore();
-
   } else if (dumpJP2 && str->getKind() == strJPX && !inlineImg) {
     // dump JPEG2000 file
     writeRawImage(str, "jp2");
@@ -612,18 +588,9 @@ void ImageOutputDev::writeImage(GfxState *state, Object *ref, Stream *str,
 
     fclose(f);
 
-    if (inlineImg) {
-      embedStr = (EmbedStream *) (str->getBaseStream());
-      getInlineImageLength(str, width, height, colorMap); // record the strean
-      embedStr->rewind();
-    }
-
     // dump CCITT file
     writeRawImage(str, "ccitt");
 
-    if (inlineImg)
-      embedStr->restore();
-
   } else if (outputPNG && !(outputTiff && colorMap &&
                             (colorMap->getColorSpace()->getMode() == csDeviceCMYK ||
                              (colorMap->getColorSpace()->getMode() == csICCBased &&
@@ -653,6 +620,7 @@ void ImageOutputDev::writeImage(GfxState *state, Object *ref, Stream *str,
 
     writeImageFile(writer, format, "png", str, width, height, colorMap);
 #endif
+    delete writer;
 
   } else if (outputTiff) {
     // output in TIFF format
@@ -684,6 +652,7 @@ void ImageOutputDev::writeImage(GfxState *state, Object *ref, Stream *str,
 
     writeImageFile(writer, format, "tif", str, width, height, colorMap);
 #endif
+    delete writer;
 
   } else {
     // output in PPM/PBM format
@@ -703,6 +672,9 @@ void ImageOutputDev::writeImage(GfxState *state, Object *ref, Stream *str,
 
     delete writer;
   }
+
+  if (inlineImg)
+      embedStr->restore();
 }
 
 GBool ImageOutputDev::tilingPatternFill(GfxState *state, Gfx *gfx, Catalog *cat, Object *str,
-- 
2.11.0