[poppler] utils/HtmlOutputDev.cc utils/HtmlOutputDev.h

Albert Astals Cid aacid at kemper.freedesktop.org
Thu Mar 15 14:57:00 PDT 2012


 utils/HtmlOutputDev.cc |  203 ++++++++++++++++++++++++++++++-------------------
 utils/HtmlOutputDev.h  |    3 
 2 files changed, 131 insertions(+), 75 deletions(-)

New commits:
commit 6d68d0d3acc8c8e0d9d310b2e1ba2b07d6bfe942
Author: Ihar Filipau <thephilips at gmail.com>
Date:   Thu Mar 15 22:56:10 2012 +0100

    pdftohtml: extract mask images even if they are not JPEG
    
    Bug #47186

diff --git a/utils/HtmlOutputDev.cc b/utils/HtmlOutputDev.cc
index 19f1c84..82464df 100644
--- a/utils/HtmlOutputDev.cc
+++ b/utils/HtmlOutputDev.cc
@@ -1280,16 +1280,9 @@ void HtmlOutputDev::drawJpegImage(GfxState *state, Stream *str)
 {
   FILE *f1;
   int c;
-  GooString *fName=new GooString(Docname);
-  fName->append("-");
-  GooString *pgNum= GooString::fromInt(pageNum);
-  GooString *imgnum= GooString::fromInt(pages->getNumImages()+1);
 
   // open the image file
-  fName->append(pgNum)->append("_")->append(imgnum)->append(".jpg");
-  delete pgNum;
-  delete imgnum;
-
+  GooString *fName=createImageFileName("jpg");
   if (!(f1 = fopen(fName->getCString(), "wb"))) {
     error(errIO, -1, "Couldn't open image file '%s'", fName->getCString());
     delete fName;
@@ -1311,74 +1304,40 @@ void HtmlOutputDev::drawJpegImage(GfxState *state, Stream *str)
   }
 }
 
-void HtmlOutputDev::drawImageMask(GfxState *state, Object *ref, Stream *str,
-				  int width, int height, GBool invert,
-				  GBool interpolate, GBool inlineImg) {
+void HtmlOutputDev::drawPngImage(GfxState *state, Stream *str, int width, int height,
+                                 GfxImageColorMap *colorMap, GBool isMask)
+{
+#ifdef ENABLE_LIBPNG
+  FILE *f1;
 
-  if (ignore||(complexMode && !xml)) {
-    OutputDev::drawImageMask(state, ref, str, width, height, invert, interpolate, inlineImg);
+  if (!colorMap && !isMask) {
+    error(errInternal, -1, "Can't have color image without a color map");
     return;
   }
-  
-  // dump JPEG file
-  if (dumpJPEG  && str->getKind() == strDCT) {
-    drawJpegImage(state, str);
-  }
-  else {
-    OutputDev::drawImageMask(state, ref, str, width, height, invert, interpolate, inlineImg);
-  }
-}
 
-void HtmlOutputDev::drawImage(GfxState *state, Object *ref, Stream *str,
-			      int width, int height, GfxImageColorMap *colorMap,
-			      GBool interpolate, int *maskColors, GBool inlineImg) {
-
-  if (ignore||(complexMode && !xml)) {
-    OutputDev::drawImage(state, ref, str, width, height, colorMap, interpolate,
-			 maskColors, inlineImg);
+  // open the image file
+  GooString *fName=createImageFileName("png");
+  if (!(f1 = fopen(fName->getCString(), "wb"))) {
+    error(errIO, -1, "Couldn't open image file '%s'", fName->getCString());
+    delete fName;
     return;
   }
-  
-  /*if( !globalParams->getErrQuiet() )
-    printf("image stream of kind %d\n", str->getKind());*/
-  // dump JPEG file
-  if (dumpJPEG && str->getKind() == strDCT) {
-    drawJpegImage(state, str);
+
+  PNGWriter *writer = new PNGWriter( isMask ? PNGWriter::MONOCHROME : PNGWriter::RGB );
+  // TODO can we calculate the resolution of the image?
+  if (!writer->init(f1, width, height, 72, 72)) {
+    error(errInternal, -1, "Can't init PNG for image '%s'", fName->getCString());
+    delete writer;
+    fclose(f1);
+    return;
   }
-  else {
-#ifdef ENABLE_LIBPNG
-    // Dump the image as a PNG file. Much of the PNG code
-    // comes from an example by Guillaume Cottenceau.
-    FILE *f1;
+
+  if (!isMask) {
     Guchar *p;
     GfxRGB rgb;
-    png_byte *row = (png_byte *) malloc(3 * width);   // 3 bytes/pixel: RGB
+    png_byte *row = (png_byte *) gmalloc(3 * width);   // 3 bytes/pixel: RGB
     png_bytep *row_pointer= &row;
 
-    // Create the image filename
-    GooString *fName=new GooString(Docname);
-    fName->append("-");
-    GooString *pgNum= GooString::fromInt(pageNum);
-    GooString *imgnum= GooString::fromInt(pages->getNumImages()+1);
-    fName->append(pgNum)->append("_")->append(imgnum)->append(".png");
-    delete pgNum;
-    delete imgnum;
-
-    // Open the image file
-    if (!(f1 = fopen(fName->getCString(), "wb"))) {
-      error(errIO, -1, "Couldn't open image file '{0:t}'", fName);
-      delete fName;
-      return;
-    }
-
-    PNGWriter *writer = new PNGWriter();
-    // TODO can we calculate the resolution of the image?
-    if (!writer->init(f1, width, height, 72, 72)) {
-        delete writer;
-        fclose(f1);
-        return;
-    }
-
     // Initialize the image stream
     ImageStream *imgStr = new ImageStream(str, width,
                         colorMap->getNumPixelComps(), colorMap->getBits());
@@ -1391,31 +1350,125 @@ void HtmlOutputDev::drawImage(GfxState *state, Object *ref, Stream *str,
       p = imgStr->getLine();
       for (int x = 0; x < width; x++) {
         colorMap->getRGB(p, &rgb);
-	// Write the RGB pixels into the row
-	row[3*x]= colToByte(rgb.r);
-	row[3*x+1]= colToByte(rgb.g);
-	row[3*x+2]= colToByte(rgb.b);
-         p += colorMap->getNumPixelComps();
+        // Write the RGB pixels into the row
+        row[3*x]= colToByte(rgb.r);
+        row[3*x+1]= colToByte(rgb.g);
+        row[3*x+2]= colToByte(rgb.b);
+        p += colorMap->getNumPixelComps();
       }
 
       if (!writer->writeRow(row_pointer)) {
+        error(errIO, -1, "Failed to write into PNG '%s'", fName->getCString());
         delete writer;
+        delete imgStr;
         fclose(f1);
         return;
       }
     }
+    gfree(row);
+    imgStr->close();
+    delete imgStr;
+  }
+  else { // isMask == true
+    ImageStream *imgStr = new ImageStream(str, width, 1, 1);
+    imgStr->reset();
 
-    writer->close();
-    delete writer;
-    fclose(f1);
+    Guchar *png_row = (Guchar *)gmalloc( width );
+
+    for (int ri = 0; ri < height; ++ri)
+    {
+      // read the row of the mask
+      Guchar *bit_row = imgStr->getLine();
+
+      // invert for PNG
+      for(int i = 0; i < width; i++)
+        png_row[i] = bit_row[i] ? 0x00 : 0xff ;
 
-    free(row);
-    pages->addImage(fName, state);
+      if (!writer->writeRow( &png_row ))
+      {
+        error(errIO, -1, "Failed to write into PNG '%s'", fName->getCString());
+        delete writer;
+        fclose(f1);
+        delete imgStr;
+        gfree(png_row);
+        return;
+      }
+    }
     imgStr->close();
     delete imgStr;
+    gfree(png_row);
+  }
+
+  str->close();
+
+  writer->close();
+  delete writer;
+  fclose(f1);
+
+  pages->addImage(fName, state);
 #else
+  return;
+#endif
+}
+
+GooString *HtmlOutputDev::createImageFileName(const char *ext)
+{
+  GooString *fName=new GooString(Docname);
+  fName->append("-");
+  GooString *pgNum= GooString::fromInt(pageNum);
+  GooString *imgnum= GooString::fromInt(pages->getNumImages()+1);
+
+  fName->append(pgNum)->append("_")->append(imgnum)->append(".")->append(ext);
+  delete pgNum;
+  delete imgnum;
+
+  return fName;
+}
+
+void HtmlOutputDev::drawImageMask(GfxState *state, Object *ref, Stream *str,
+				  int width, int height, GBool invert,
+				  GBool interpolate, GBool inlineImg) {
+
+  if (ignore||(complexMode && !xml)) {
+    OutputDev::drawImageMask(state, ref, str, width, height, invert, interpolate, inlineImg);
+    return;
+  }
+  
+  // dump JPEG file
+  if (dumpJPEG  && str->getKind() == strDCT) {
+    drawJpegImage(state, str);
+  }
+  else {
+#ifdef ENABLE_LIBPNG
+    drawPngImage(state, str, width, height, NULL, gTrue);
+#else
+    OutputDev::drawImageMask(state, ref, str, width, height, invert, interpolate, inlineImg);
+#endif
+  }
+}
+
+void HtmlOutputDev::drawImage(GfxState *state, Object *ref, Stream *str,
+			      int width, int height, GfxImageColorMap *colorMap,
+			      GBool interpolate, int *maskColors, GBool inlineImg) {
+
+  if (ignore||(complexMode && !xml)) {
     OutputDev::drawImage(state, ref, str, width, height, colorMap, interpolate,
 			 maskColors, inlineImg);
+    return;
+  }
+  
+  /*if( !globalParams->getErrQuiet() )
+    printf("image stream of kind %d\n", str->getKind());*/
+  // dump JPEG file
+  if (dumpJPEG && str->getKind() == strDCT) {
+    drawJpegImage(state, str);
+  }
+  else {
+#ifdef ENABLE_LIBPNG
+    drawPngImage(state, str, width, height, colorMap );
+#else
+    OutputDev::drawImage(state, ref, str, width, height, colorMap, interpolate,
+                         maskColors, inlineImg);
 #endif
   }
 }
diff --git a/utils/HtmlOutputDev.h b/utils/HtmlOutputDev.h
index b730ead..2f35759 100644
--- a/utils/HtmlOutputDev.h
+++ b/utils/HtmlOutputDev.h
@@ -323,6 +323,9 @@ private:
   int getOutlinePageNum(OutlineItem *item);
 #endif
   void drawJpegImage(GfxState *state, Stream *str);
+  void drawPngImage(GfxState *state, Stream *str, int width, int height,
+                    GfxImageColorMap *colorMap, GBool isMask = gFalse);
+  GooString *createImageFileName(const char *ext);
 
   FILE *fContentsFrame;
   FILE *page;                   // html file


More information about the poppler mailing list