[PATCH] Add the -jpeg flag to pdftoppm to output to JPEG
Stefan Thomas
thomas at eload24.com
Mon Sep 7 01:55:40 PDT 2009
Added generic ImgWriter class and SplashBitmap::writeImgFile method.
---
goo/ImgWriter.h | 28 ++++++++++++++
goo/JpegWriter.cc | 95 ++++++++++++++++++++++++++++++++++++++++++++++++
goo/JpegWriter.h | 45 +++++++++++++++++++++++
goo/Makefile.am | 2 +
goo/PNGWriter.cc | 4 +-
goo/PNGWriter.h | 9 +++--
splash/SplashBitmap.cc | 46 ++++++++++++++++-------
splash/SplashBitmap.h | 4 +-
splash/SplashTypes.h | 10 +++++
utils/pdftoppm.1 | 3 ++
utils/pdftoppm.cc | 21 ++++++++---
11 files changed, 240 insertions(+), 27 deletions(-)
create mode 100644 goo/ImgWriter.h
create mode 100644 goo/JpegWriter.cc
create mode 100644 goo/JpegWriter.h
diff --git a/goo/ImgWriter.h b/goo/ImgWriter.h
new file mode 100644
index 0000000..147e922
--- /dev/null
+++ b/goo/ImgWriter.h
@@ -0,0 +1,28 @@
+//========================================================================
+//
+// ImgWriter.h
+//
+// This file is licensed under the GPLv2 or later
+//
+// Copyright (C) 2009 Stefan Thomas <thomas at eload24.com>
+//
+//========================================================================
+
+#ifndef IMGWRITER_H
+#define IMGWRITER_H
+
+#include <config.h>
+#include <cstdio>
+
+class ImgWriter
+{
+ public:
+ virtual bool init(FILE *f, int width, int height) = 0;
+
+ virtual bool writePointers(unsigned char **rowPointers, int rowCount) = 0;
+ virtual bool writeRow(unsigned char **row) = 0;
+
+ virtual bool close() = 0;
+};
+
+#endif
diff --git a/goo/JpegWriter.cc b/goo/JpegWriter.cc
new file mode 100644
index 0000000..6946dd9
--- /dev/null
+++ b/goo/JpegWriter.cc
@@ -0,0 +1,95 @@
+//========================================================================
+//
+// JpegWriter.cc
+//
+// This file is licensed under the GPLv2 or later
+//
+// Copyright (C) 2009 Stefan Thomas <thomas at eload24.com>
+// Copyright (C) 2009 Warren Toomey <wkt at tuhs.org>
+// Copyright (C) 2009 Shen Liang <shenzhuxi at gmail.com>
+// Copyright (C) 2009 Albert Astals Cid <aacid at kde.org>
+//
+//========================================================================
+
+#include "JpegWriter.h"
+
+#ifdef ENABLE_LIBJPEG
+
+#include "poppler/Error.h"
+
+void outputMessage(j_common_ptr cinfo)
+{
+ char buffer[JMSG_LENGTH_MAX];
+
+ // Create the message
+ (*cinfo->err->format_message) (cinfo, buffer);
+
+ // Send it to poppler's error handler
+ error(-1, buffer);
+}
+
+JpegWriter::JpegWriter()
+{
+}
+
+JpegWriter::~JpegWriter()
+{
+ // cleanup
+ jpeg_destroy_compress(&cinfo);
+}
+
+bool JpegWriter::init(FILE *f, int width, int height)
+{
+ // Setup error handler
+ cinfo.err = jpeg_std_error(&jerr);
+ jerr.output_message = &outputMessage;
+
+ // Initialize libjpeg
+ jpeg_create_compress(&cinfo);
+
+ // Set destination file
+ jpeg_stdio_dest(&cinfo, f);
+
+ // Set libjpeg configuration
+ cinfo.image_width = width;
+ cinfo.image_height = height;
+ cinfo.input_components = 3; /* # of color components per pixel */
+ cinfo.in_color_space = JCS_RGB; /* colorspace of input image */
+ jpeg_set_defaults(&cinfo);
+
+ // Set quality
+ //jpeg_set_quality(&cinfo, 80, true);
+
+ // Use progressive mode
+ //jpeg_simple_progression(&cinfo);
+
+ // Get ready for data
+ jpeg_start_compress(&cinfo, TRUE);
+
+ return true;
+}
+
+bool JpegWriter::writePointers(unsigned char **rowPointers, int rowCount)
+{
+ // Write all rows to the file
+ jpeg_write_scanlines(&cinfo, rowPointers, rowCount);
+
+ return true;
+}
+
+bool JpegWriter::writeRow(unsigned char **row)
+{
+ // Write the row to the file
+ jpeg_write_scanlines(&cinfo, row, 1);
+
+ return true;
+}
+
+bool JpegWriter::close()
+{
+ jpeg_finish_compress(&cinfo);
+
+ return true;
+}
+
+#endif
diff --git a/goo/JpegWriter.h b/goo/JpegWriter.h
new file mode 100644
index 0000000..b35dd80
--- /dev/null
+++ b/goo/JpegWriter.h
@@ -0,0 +1,45 @@
+//========================================================================
+//
+// JpegWriter.h
+//
+// This file is licensed under the GPLv2 or later
+//
+// Copyright (C) 2009 Stefan Thomas <thomas at eload24.com>
+// Copyright (C) 2009 Warren Toomey <wkt at tuhs.org>
+// Copyright (C) 2009 Shen Liang <shenzhuxi at gmail.com>
+// Copyright (C) 2009 Albert Astals Cid <aacid at kde.org>
+//
+//========================================================================
+
+#ifndef JPEGWRITER_H
+#define JPEGWRITER_H
+
+#include <config.h>
+
+#ifdef ENABLE_LIBJPEG
+
+#include <cstdio>
+#include <jpeglib.h>
+#include "ImgWriter.h"
+
+class JpegWriter : public ImgWriter
+{
+ public:
+ JpegWriter();
+ ~JpegWriter();
+
+ bool init(FILE *f, int width, int height);
+
+ bool writePointers(unsigned char **rowPointers, int rowCount);
+ bool writeRow(unsigned char **row);
+
+ bool close();
+
+ private:
+ struct jpeg_compress_struct cinfo;
+ struct jpeg_error_mgr jerr;
+};
+
+#endif
+
+#endif
diff --git a/goo/Makefile.am b/goo/Makefile.am
index f10fd15..ad11af5 100644
--- a/goo/Makefile.am
+++ b/goo/Makefile.am
@@ -15,6 +15,7 @@ poppler_goo_include_HEADERS = \
gfile.h \
FixedPoint.h \
PNGWriter.h \
+ JpegWriter.h \
gstrtod.h
endif
@@ -32,4 +33,5 @@ libgoo_la_SOURCES = \
gmem.cc \
FixedPoint.cc \
PNGWriter.cc \
+ JpegWriter.cc \
gstrtod.cc
diff --git a/goo/PNGWriter.cc b/goo/PNGWriter.cc
index 864c976..767e02f 100644
--- a/goo/PNGWriter.cc
+++ b/goo/PNGWriter.cc
@@ -71,7 +71,7 @@ bool PNGWriter::init(FILE *f, int width, int height)
return true;
}
-bool PNGWriter::writePointers(png_bytep *rowPointers)
+bool PNGWriter::writePointers(unsigned char **rowPointers, int rowCount)
{
png_write_image(png_ptr, rowPointers);
/* write bytes */
@@ -83,7 +83,7 @@ bool PNGWriter::writePointers(png_bytep *rowPointers)
return true;
}
-bool PNGWriter::writeRow(png_bytep *row)
+bool PNGWriter::writeRow(unsigned char **row)
{
// Write the row to the file
png_write_rows(png_ptr, row, 1);
diff --git a/goo/PNGWriter.h b/goo/PNGWriter.h
index 0540bd7..85e21f9 100644
--- a/goo/PNGWriter.h
+++ b/goo/PNGWriter.h
@@ -19,8 +19,9 @@
#include <cstdio>
#include <png.h>
+#include "ImgWriter.h"
-class PNGWriter
+class PNGWriter : public ImgWriter
{
public:
PNGWriter();
@@ -28,8 +29,8 @@ class PNGWriter
bool init(FILE *f, int width, int height);
- bool writePointers(png_bytep *rowPointers);
- bool writeRow(png_bytep *row);
+ bool writePointers(unsigned char **rowPointers, int rowCount);
+ bool writeRow(unsigned char **row);
bool close();
@@ -40,4 +41,4 @@ class PNGWriter
#endif
-#endif
\ No newline at end of file
+#endif
diff --git a/splash/SplashBitmap.cc b/splash/SplashBitmap.cc
index 25a71a0..2337a62 100644
--- a/splash/SplashBitmap.cc
+++ b/splash/SplashBitmap.cc
@@ -14,6 +14,7 @@
// Copyright (C) 2006, 2009 Albert Astals Cid <aacid at kde.org>
// Copyright (C) 2007 Ilmari Heikkinen <ilmari.heikkinen at gmail.com>
// Copyright (C) 2009 Shen Liang <shenzhuxi at gmail.com>
+// Copyright (C) 2009 Stefan Thomas <thomas at eload24.com>
//
// To see a description of the changes please see the Changelog file that
// came with your tarball or type make ChangeLog if you are building from git
@@ -32,7 +33,8 @@
#include "SplashErrorCodes.h"
#include "SplashBitmap.h"
#include "poppler/Error.h"
-#include "PNGWriter.h"
+#include "goo/JpegWriter.h"
+#include "goo/PNGWriter.h"
//------------------------------------------------------------------------
// SplashBitmap
@@ -244,7 +246,7 @@ Guchar SplashBitmap::getAlpha(int x, int y) {
return alpha[y * width + x];
}
-SplashError SplashBitmap::writePNGFile(char *fileName) {
+SplashError SplashBitmap::writeImgFile(SplashImageFileFormat format, char *fileName) {
FILE *f;
SplashError e;
@@ -252,23 +254,40 @@ SplashError SplashBitmap::writePNGFile(char *fileName) {
return splashErrOpenFile;
}
- e = writePNGFile(f);
+ e = writeImgFile(format, f);
fclose(f);
return e;
}
-SplashError SplashBitmap::writePNGFile(FILE *f) {
-#ifndef ENABLE_LIBPNG
- error(-1, "PNG support not compiled in");
- return splashErrGeneric;
-#else
+SplashError SplashBitmap::writeImgFile(SplashImageFileFormat format, FILE *f) {
+ ImgWriter *writer;
+
+ switch (format) {
+ #ifdef ENABLE_LIBPNG
+ case splashFormatPng:
+ writer = new PNGWriter();
+ break;
+ #endif
+
+ #ifdef ENABLE_LIBJPEG
+ case splashFormatJpeg:
+ writer = new JpegWriter();
+ break;
+ #endif
+
+ default:
+ // Not the greatest error message, but users of this function should
+ // have already checked whether their desired format is compiled in.
+ error(-1, "Support for this image type not compiled in");
+ return splashErrGeneric;
+ }
+
if (mode != splashModeRGB8 && mode != splashModeMono8 && mode != splashModeMono1) {
error(-1, "unsupported SplashBitmap mode");
return splashErrGeneric;
}
- PNGWriter *writer = new PNGWriter();
if (!writer->init(f, width, height)) {
delete writer;
return splashErrGeneric;
@@ -278,14 +297,14 @@ SplashError SplashBitmap::writePNGFile(FILE *f) {
case splashModeRGB8:
{
SplashColorPtr row;
- png_bytep *row_pointers = new png_bytep[height];
+ unsigned char **row_pointers = new unsigned char*[height];
row = data;
for (int y = 0; y < height; ++y) {
row_pointers[y] = row;
row += rowSize;
}
- if (!writer->writePointers(row_pointers)) {
+ if (!writer->writePointers(row_pointers, height)) {
delete[] row_pointers;
delete writer;
return splashErrGeneric;
@@ -296,7 +315,7 @@ SplashError SplashBitmap::writePNGFile(FILE *f) {
case splashModeMono8:
{
- png_byte *row = new png_byte[3 * width];
+ unsigned char *row = new unsigned char[3 * width];
for (int y = 0; y < height; y++) {
// Convert into a PNG row
for (int x = 0; x < width; x++) {
@@ -317,7 +336,7 @@ SplashError SplashBitmap::writePNGFile(FILE *f) {
case splashModeMono1:
{
- png_byte *row = new png_byte[3 * width];
+ unsigned char *row = new unsigned char[3 * width];
for (int y = 0; y < height; y++) {
// Convert into a PNG row
for (int x = 0; x < width; x++) {
@@ -349,5 +368,4 @@ SplashError SplashBitmap::writePNGFile(FILE *f) {
delete writer;
return splashOk;
-#endif
}
diff --git a/splash/SplashBitmap.h b/splash/SplashBitmap.h
index 5085763..66b65ca 100644
--- a/splash/SplashBitmap.h
+++ b/splash/SplashBitmap.h
@@ -58,8 +58,8 @@ public:
SplashError writePNMFile(char *fileName);
SplashError writePNMFile(FILE *f);
- SplashError writePNGFile(char *fileName);
- SplashError writePNGFile(FILE *f);
+ SplashError writeImgFile(SplashImageFileFormat format, char *fileName);
+ SplashError writeImgFile(SplashImageFileFormat format, FILE *f);
void getPixel(int x, int y, SplashColorPtr pixel);
Guchar getAlpha(int x, int y);
diff --git a/splash/SplashTypes.h b/splash/SplashTypes.h
index a868652..2fe30f9 100644
--- a/splash/SplashTypes.h
+++ b/splash/SplashTypes.h
@@ -150,4 +150,14 @@ struct SplashScreenParams {
typedef int SplashError;
+
+//------------------------------------------------------------------------
+// image file formats
+//------------------------------------------------------------------------
+
+enum SplashImageFileFormat {
+ splashFormatJpeg,
+ splashFormatPng
+};
+
#endif
diff --git a/utils/pdftoppm.1 b/utils/pdftoppm.1
index ecadf22..fee97f8 100644
--- a/utils/pdftoppm.1
+++ b/utils/pdftoppm.1
@@ -71,6 +71,9 @@ Generate a grayscale PGM file (instead of a color PPM file).
.B \-png
Generates a PNG file instead a PPM file.
.TP
+.B \-jpeg
+Generates a JPEG file instead a PPM file.
+.TP
.BI \-freetype " yes | no"
Enable or disable FreeType (a TrueType / Type 1 font rasterizer).
This defaults to "yes".
diff --git a/utils/pdftoppm.cc b/utils/pdftoppm.cc
index 38c26fd..20c4eb6 100644
--- a/utils/pdftoppm.cc
+++ b/utils/pdftoppm.cc
@@ -56,6 +56,7 @@ static GBool useCropBox = gFalse;
static GBool mono = gFalse;
static GBool gray = gFalse;
static GBool png = gFalse;
+static GBool jpeg = gFalse;
static char enableFreeTypeStr[16] = "";
static char antialiasStr[16] = "";
static char vectorAntialiasStr[16] = "";
@@ -105,6 +106,10 @@ static const ArgDesc argDesc[] = {
{"-png", argFlag, &png, 0,
"generate a PNG file"},
#endif
+#if ENABLE_LIBJPEG
+ {"-jpeg", argFlag, &jpeg, 0,
+ "generate a JPEG file"},
+#endif
#if HAVE_FREETYPE_FREETYPE_H | HAVE_FREETYPE_H
{"-freetype", argString, enableFreeTypeStr, sizeof(enableFreeTypeStr),
"enable FreeType font rasterizer: yes, no"},
@@ -140,6 +145,8 @@ static void savePageSlice(PDFDoc *doc,
int pg, int x, int y, int w, int h,
double pg_w, double pg_h,
char *ppmFile) {
+ SplashBitmap *bitmap = splashOut->getBitmap();
+
if (w == 0) w = (int)ceil(pg_w);
if (h == 0) h = (int)ceil(pg_h);
w = (x+w > pg_w ? (int)ceil(pg_w-x) : w);
@@ -152,15 +159,19 @@ static void savePageSlice(PDFDoc *doc,
);
if (ppmFile != NULL) {
if (png) {
- splashOut->getBitmap()->writePNGFile(ppmFile);
+ bitmap->writeImgFile(splashFormatPng, ppmFile);
+ } else if (jpeg) {
+ bitmap->writeImgFile(splashFormatJpeg, ppmFile);
} else {
- splashOut->getBitmap()->writePNMFile(ppmFile);
+ bitmap->writePNMFile(ppmFile);
}
} else {
if (png) {
- splashOut->getBitmap()->writePNGFile(stdout);
+ bitmap->writeImgFile(splashFormatPng, stdout);
+ } else if (jpeg) {
+ bitmap->writeImgFile(splashFormatJpeg, stdout);
} else {
- splashOut->getBitmap()->writePNMFile(stdout);
+ bitmap->writePNMFile(stdout);
}
}
}
@@ -301,7 +312,7 @@ int main(int argc, char *argv[]) {
if (ppmRoot != NULL) {
snprintf(ppmFile, PPM_FILE_SZ, "%.*s-%0*d.%s",
PPM_FILE_SZ - 32, ppmRoot, pg_num_len, pg,
- png ? "png" : mono ? "pbm" : gray ? "pgm" : "ppm");
+ png ? "png" : jpeg ? "jpg" : mono ? "pbm" : gray ? "pgm" : "ppm");
savePageSlice(doc, splashOut, pg, x, y, w, h, pg_w, pg_h, ppmFile);
} else {
savePageSlice(doc, splashOut, pg, x, y, w, h, pg_w, pg_h, NULL);
--
1.6.0.4
--------------050104000009090502070400--
More information about the poppler
mailing list