[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