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