Merged patches into one and fixed last two compiler warnings.

@Albert: Assuming you agree with me on the duplicate code issue, this should be ready to be committed.

On 7/16/2010 3:32 PM, Albert Astals Cid wrote:
A Dissabte, 10 de juliol de 2010, Stefan Thomas va escriure:
Hello!

I've got two new patches for the cause.

The first one adds transparent PNG support to PNGWriter and
SplashBitmap. The uses for this are varied and many, so I think it makes
sense to add this to the mainline, even though I don't have the pdftoppm
patch to go along with it. (We're using it in a custom SplashOutputDev.)
Seems like it duplicates some code from the other method, would it be possible
to merge them a bit more?

The second one fixes a nasty bug in SplashBitmap that causes "pdftoppm
-jpeg" to randomly produce corrupt images. Currently SplashBitmap frees
its temporary buffers and later calls ImgWriter::close(). Problem is
libjpeg still uses these temporary buffers during
jpeg_finish_compress(). So if they've been reclaimed - bad things
happen. Usually libjpeg aborts and produces an image with the bottom
fifty or so rows missing. The patch also fixes the SplashBitmap throwing
a splashErrGeneric despite success, which was due to a missing question
mark before writer->close().
valgrind does not complain about it when i do
   valgrind ./utils/pdftoppm -jpeg ~/pdf_reference_1-7.pdf -f 1 -l 1 foo

Are you sure that is the problem?

Albert

Hope you find it useful.

Cheers,

Stefan Thomas
_______________________________________________
poppler mailing list
[email protected]
http://lists.freedesktop.org/mailman/listinfo/poppler


>From 4af9d7140ffbca634ecac38564e274bfcc00238b Mon Sep 17 00:00:00 2001
From: Stefan Thomas <[email protected]>
Date: Fri, 9 Jul 2010 22:59:04 +0100
Subject: [PATCH] Add support for transparent PNGs to PNGWriter and SplashBitmap.

---
 goo/PNGWriter.cc       |    5 +-
 goo/PNGWriter.h        |    4 +-
 splash/SplashBitmap.cc |  137 +++++++++++++++++++++++++++++++++++++++++++++---
 splash/SplashBitmap.h  |    5 ++-
 splash/SplashTypes.h   |    3 +-
 5 files changed, 142 insertions(+), 12 deletions(-)

diff --git a/goo/PNGWriter.cc b/goo/PNGWriter.cc
index aebab9e..1aa9532 100644
--- a/goo/PNGWriter.cc
+++ b/goo/PNGWriter.cc
@@ -18,8 +18,9 @@
 
 #include "poppler/Error.h"
 
-PNGWriter::PNGWriter()
+PNGWriter::PNGWriter(GBool withAlphaChannel)
 {
+       this->withAlphaChannel = withAlphaChannel;
 }
 
 PNGWriter::~PNGWriter()
@@ -59,7 +60,7 @@ bool PNGWriter::init(FILE *f, int width, int height, int 
hDPI, int vDPI)
        png_set_compression_level(png_ptr, Z_BEST_COMPRESSION);
 
        png_byte bit_depth = 8;
-       png_byte color_type = PNG_COLOR_TYPE_RGB;
+       png_byte color_type = (withAlphaChannel) ? PNG_COLOR_TYPE_RGB_ALPHA : 
PNG_COLOR_TYPE_RGB;
        png_byte interlace_type = PNG_INTERLACE_NONE;
 
        png_set_IHDR(png_ptr, info_ptr, width, height, bit_depth, color_type, 
interlace_type, PNG_COMPRESSION_TYPE_DEFAULT, PNG_FILTER_TYPE_DEFAULT);
diff --git a/goo/PNGWriter.h b/goo/PNGWriter.h
index 64ffc67..70bc86d 100644
--- a/goo/PNGWriter.h
+++ b/goo/PNGWriter.h
@@ -22,11 +22,12 @@
 #include <cstdio>
 #include <png.h>
 #include "ImgWriter.h"
+#include "goo/gtypes.h"
 
 class PNGWriter : public ImgWriter
 {
        public:
-               PNGWriter();
+               PNGWriter(GBool withAlphaChannel = gFalse);
                ~PNGWriter();
                
                bool init(FILE *f, int width, int height, int hDPI, int vDPI);
@@ -39,6 +40,7 @@ class PNGWriter : public ImgWriter
        private:
                png_structp png_ptr;
                png_infop info_ptr;
+               GBool withAlphaChannel;
 };
 
 #endif
diff --git a/splash/SplashBitmap.cc b/splash/SplashBitmap.cc
index f983439..46301c9 100644
--- a/splash/SplashBitmap.cc
+++ b/splash/SplashBitmap.cc
@@ -288,13 +288,20 @@ SplashError 
SplashBitmap::writeImgFile(SplashImageFileFormat format, char *fileN
 
 SplashError SplashBitmap::writeImgFile(SplashImageFileFormat format, FILE *f, 
int hDPI, int vDPI) {
   ImgWriter *writer;
-       SplashError e;
+  SplashError e;
+  
+  GBool withAlpha = gFalse;
   
   switch (format) {
     #ifdef ENABLE_LIBPNG
     case splashFormatPng:
          writer = new PNGWriter();
       break;
+    
+    case splashFormatPngAlpha:
+         writer = new PNGWriter(gTrue);
+         withAlpha = gTrue;
+      break;
     #endif
 
     #ifdef ENABLE_LIBJPEG
@@ -310,12 +317,15 @@ SplashError 
SplashBitmap::writeImgFile(SplashImageFileFormat format, FILE *f, in
       return splashErrGeneric;
   }
 
-       e = writeImgFile(writer, f, hDPI, vDPI);
-       delete writer;
-       return e;
+  e = writeImgFile(writer, f, hDPI, vDPI, withAlpha);
+  delete writer;
+  return e;
 }
 
-SplashError SplashBitmap::writeImgFile(ImgWriter *writer, FILE *f, int hDPI, 
int vDPI) {
+SplashError SplashBitmap::writeImgFile(ImgWriter *writer, FILE *f, int hDPI, 
int vDPI, GBool withAlpha)
+{
+  SplashError e;
+  
   if (mode != splashModeRGB8 && mode != splashModeMono8 && mode != 
splashModeMono1 && mode != splashModeXBGR8) {
     error(-1, "unsupported SplashBitmap mode");
     return splashErrGeneric;
@@ -324,7 +334,20 @@ SplashError SplashBitmap::writeImgFile(ImgWriter *writer, 
FILE *f, int hDPI, int
   if (!writer->init(f, width, height, hDPI, vDPI)) {
     return splashErrGeneric;
   }
+  
+  if (!withAlpha) {
+    e = writeImgDataRGB(writer);
+  } else {
+    e = writeImgDataRGBA(writer);
+  }
+  
+  if (e) return e;
 
+  return splashOk;
+}
+
+SplashError SplashBitmap::writeImgDataRGB(ImgWriter *writer)
+{
   switch (mode) {
     case splashModeRGB8:
     {
@@ -340,6 +363,9 @@ SplashError SplashBitmap::writeImgFile(ImgWriter *writer, 
FILE *f, int hDPI, int
         delete[] row_pointers;
         return splashErrGeneric;
       }
+      if (!writer->close()) {
+        return splashErrGeneric;
+      }
       delete[] row_pointers;
     }
     break;
@@ -360,6 +386,9 @@ SplashError SplashBitmap::writeImgFile(ImgWriter *writer, 
FILE *f, int hDPI, int
           return splashErrGeneric;
         }
       }
+      if (!writer->close()) {
+        return splashErrGeneric;
+      }
       delete[] row;
     }
     break;
@@ -380,6 +409,9 @@ SplashError SplashBitmap::writeImgFile(ImgWriter *writer, 
FILE *f, int hDPI, int
           return splashErrGeneric;
         }
       }
+      if (!writer->close()) {
+        return splashErrGeneric;
+      }
       delete[] row;
     }
     break;
@@ -400,18 +432,109 @@ SplashError SplashBitmap::writeImgFile(ImgWriter 
*writer, FILE *f, int hDPI, int
           return splashErrGeneric;
         }
       }
+      if (!writer->close()) {
+        return splashErrGeneric;
+      }
       delete[] row;
     }
     break;
     
     default:
+      // can't happen
+      return splashErrGeneric;
+  }
+}
+
+SplashError SplashBitmap::writeImgDataRGBA(ImgWriter *writer)
+{
+  unsigned char *row = new unsigned char[4 * width];
+      
+  switch (mode) {
+    case splashModeRGB8:
+    {
+      for (int y = 0; y < height; y++) {
+        // Convert into a PNG row
+        for (int x = 0; x < width; x++) {
+          row[4*x] = data[y * rowSize + 3*x];
+          row[4*x+1] = data[y * rowSize + 3*x + 1];
+          row[4*x+2] = data[y * rowSize + 3*x + 2];
+          row[4*x+3] = alpha[y * width + x];
+        }
+
+        if (!writer->writeRow(&row)) {
+          delete[] row;
+          return splashErrGeneric;
+        }
+      }
+    }
+    break;
+    
+    case splashModeXBGR8:
+    {
+      for (int y = 0; y < height; y++) {
+        // Convert into a PNG row
+        for (int x = 0; x < width; x++) {
+          row[4*x] = data[y * rowSize + x * 4 + 2];
+          row[4*x+1] = data[y * rowSize + x * 4 + 1];
+          row[4*x+2] = data[y * rowSize + x * 4];
+          row[4*x+3] = alpha[y * width + x];
+        }
+
+        if (!writer->writeRow(&row)) {
+          delete[] row;
+          return splashErrGeneric;
+        }
+      }
+    }
+    break;
+    
+    case splashModeMono8:
+    {
+      for (int y = 0; y < height; y++) {
+        // Convert into a PNG row
+        for (int x = 0; x < width; x++) {
+          row[4*x] = data[y * rowSize + x];
+          row[4*x+1] = data[y * rowSize + x];
+          row[4*x+2] = data[y * rowSize + x];
+          row[4*x+3] = alpha[y * width + x];
+        }
+
+        if (!writer->writeRow(&row)) {
+          delete[] row;
+          return splashErrGeneric;
+        }
+      }
+    }
+    break;
+    
+    case splashModeMono1:
+    {
+      for (int y = 0; y < height; y++) {
+        // Convert into a PNG row
+        for (int x = 0; x < width; x++) {
+          getPixel(x, y, &row[4*x]);
+          row[4*x+1] = row[4*x];
+          row[4*x+2] = row[4*x];
+          row[4*x+3] = alpha[y * width + x];
+        }
+
+        if (!writer->writeRow(&row)) {
+          delete[] row;
+          return splashErrGeneric;
+        }
+      }
+    }
+    break;
+    
+    default:
     // can't happen
     break;
   }
   
-  if (writer->close()) {
+  if (!writer->close()) {
     return splashErrGeneric;
   }
-
+  delete[] row;
+  
   return splashOk;
 }
diff --git a/splash/SplashBitmap.h b/splash/SplashBitmap.h
index e741a91..ec5b397 100644
--- a/splash/SplashBitmap.h
+++ b/splash/SplashBitmap.h
@@ -65,13 +65,16 @@ public:
   
   SplashError writeImgFile(SplashImageFileFormat format, char *fileName, int 
hDPI, int vDPI);
   SplashError writeImgFile(SplashImageFileFormat format, FILE *f, int hDPI, 
int vDPI);
-  SplashError writeImgFile(ImgWriter *writer, FILE *f, int hDPI, int vDPI);
+  SplashError writeImgFile(ImgWriter *writer, FILE *f, int hDPI, int vDPI, 
GBool withAlpha = gFalse);
 
   void getPixel(int x, int y, SplashColorPtr pixel);
   Guchar getAlpha(int x, int y);
 
 private:
 
+  SplashError writeImgDataRGB(ImgWriter *writer);
+  SplashError writeImgDataRGBA(ImgWriter *writer);
+
   int width, height;           // size of bitmap
   int rowSize;                 // size of one row of data, in bytes
                                //   - negative for bottom-up bitmaps
diff --git a/splash/SplashTypes.h b/splash/SplashTypes.h
index 993dd46..3e34ea7 100644
--- a/splash/SplashTypes.h
+++ b/splash/SplashTypes.h
@@ -160,7 +160,8 @@ typedef int SplashError;
 
 enum SplashImageFileFormat {
   splashFormatJpeg,
-  splashFormatPng
+  splashFormatPng,
+  splashFormatPngAlpha
 };
 
 #endif
-- 
1.7.0.4

_______________________________________________
poppler mailing list
[email protected]
http://lists.freedesktop.org/mailman/listinfo/poppler

Reply via email to