[PATCH] Add support for transparent PNGs to PNGWriter and SplashBitmap.

Stefan Thomas thomas at eload24.com
Fri Jul 9 14:59:04 PDT 2010


---
 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


--------------070403020506040002070906--


More information about the poppler mailing list