Hello there,
A while back a fellow by the name of Adrian Johnson contributed a patch
that added a new utility "pdftocairo". We've been using the tool for a
couple of months and have made a few updates to it. I'm attaching the
original patch as well as the updates.
It supports PS, PDF, SVG, PNG and JPEG output formats.
Cheers,
Stefan Thomas
>From bcbb9ccb153f112580f14369c416cdbc6077abb5 Mon Sep 17 00:00:00 2001
From: Adrian Johnson <ajohn...@redneon.com>
Date: Fri, 11 Dec 2009 18:46:23 +1030
Subject: [PATCH 1/6] Add pdftocairo util
---
utils/Makefile.am | 20 +++-
utils/pdftocairo.cc | 379 +++++++++++++++++++++++++++++++++++++++++++++++++++
2 files changed, 397 insertions(+), 2 deletions(-)
create mode 100644 utils/pdftocairo.cc
diff --git a/utils/Makefile.am b/utils/Makefile.am
index e57c71b..ac08b5e 100644
--- a/utils/Makefile.am
+++ b/utils/Makefile.am
@@ -17,7 +17,8 @@ INCLUDES = \
-I$(top_srcdir)/poppler \
$(UTILS_CFLAGS) \
$(FONTCONFIG_CFLAGS) \
- $(ABIWORD_CFLAGS)
+ $(ABIWORD_CFLAGS) \
+ $(CAIRO_CFLAGS)
LDADD = \
$(top_builddir)/poppler/libpoppler.la \
@@ -36,6 +37,20 @@ pdftoabw_binary = pdftoabw
endif
+if BUILD_CAIRO_OUTPUT
+
+pdftocairo_SOURCES = \
+ pdftocairo.cc \
+ $(common)
+
+pdftocairo_LDADD = $(LDADD) $(CAIRO_LIBS) \
+ $(top_builddir)/poppler/libpoppler-cairo.la
+
+
+pdftocairo_binary = pdftocairo
+
+endif
+
AM_LDFLAGS = @auto_import_flags@
bin_PROGRAMS = \
@@ -46,7 +61,8 @@ bin_PROGRAMS = \
pdftotext \
pdftohtml \
$(pdftoppm_binary) \
- $(pdftoabw_binary)
+ $(pdftoabw_binary) \
+ $(pdftocairo_binary)
dist_man1_MANS = \
pdffonts.1 \
diff --git a/utils/pdftocairo.cc b/utils/pdftocairo.cc
new file mode 100644
index 0000000..8540b42
--- /dev/null
+++ b/utils/pdftocairo.cc
@@ -0,0 +1,379 @@
+//========================================================================
+//
+// pdftocairo.cc
+//
+// Copyright 2003 Glyph & Cog, LLC
+//
+//========================================================================
+
+//========================================================================
+//
+// Modified under the Poppler project - http://poppler.freedesktop.org
+//
+// All changes made under the Poppler project to this file are licensed
+// under GPL version 2 or later
+//
+// Copyright (C) 2007 Ilmari Heikkinen <ilmari.heikki...@gmail.com>
+// Copyright (C) 2008 Richard Airlie <richard.air...@maglabs.net>
+// Copyright (C) 2009 Michael K. Johnson <a1...@danlj.org>
+// Copyright (C) 2009 Shen Liang <shenzh...@gmail.com>
+// Copyright (C) 2009 Stefan Thomas <tho...@eload24.com>
+// Copyright (C) 2009 Adrian Johnson <ajohn...@redneon.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
+//
+//========================================================================
+
+#include "config.h"
+#include <poppler-config.h>
+#include <stdio.h>
+#include <math.h>
+#include <cairo.h>
+#include <cairo-ps.h>
+#include <cairo-pdf.h>
+#include "parseargs.h"
+#include "goo/gmem.h"
+#include "goo/GooString.h"
+#include "GlobalParams.h"
+#include "Object.h"
+#include "PDFDoc.h"
+#include "CairoOutputDev.h"
+
+#define OUT_FILE_SZ 512
+
+static int firstPage = 1;
+static int lastPage = 0;
+static double resolution = 0.0;
+static double x_resolution = 150.0;
+static double y_resolution = 150.0;
+static int scaleTo = 0;
+static int x_scaleTo = 0;
+static int y_scaleTo = 0;
+static int x = 0;
+static int y = 0;
+static int w = 0;
+static int h = 0;
+static int sz = 0;
+static GBool useCropBox = gFalse;
+static GBool png = gFalse;
+static GBool ps = gFalse;
+static GBool pdf = gFalse;
+static char ownerPassword[33] = "";
+static char userPassword[33] = "";
+static GBool quiet = gFalse;
+static GBool printVersion = gFalse;
+static GBool printHelp = gFalse;
+
+static const ArgDesc argDesc[] = {
+ {"-f", argInt, &firstPage, 0,
+ "first page to print"},
+ {"-l", argInt, &lastPage, 0,
+ "last page to print"},
+
+ {"-r", argFP, &resolution, 0,
+ "resolution, in DPI (default is 150)"},
+ {"-rx", argFP, &x_resolution, 0,
+ "X resolution, in DPI (default is 150)"},
+ {"-ry", argFP, &y_resolution, 0,
+ "Y resolution, in DPI (default is 150)"},
+ {"-scale-to", argInt, &scaleTo, 0,
+ "scales each page to fit within scale-to*scale-to pixel box"},
+ {"-scale-to-x", argInt, &x_scaleTo, 0,
+ "scales each page horizontally to fit in scale-to-x pixels"},
+ {"-scale-to-y", argInt, &y_scaleTo, 0,
+ "scales each page vertically to fit in scale-to-y pixels"},
+
+ {"-x", argInt, &x, 0,
+ "x-coordinate of the crop area top left corner"},
+ {"-y", argInt, &y, 0,
+ "y-coordinate of the crop area top left corner"},
+ {"-W", argInt, &w, 0,
+ "width of crop area in pixels (default is 0)"},
+ {"-H", argInt, &h, 0,
+ "height of crop area in pixels (default is 0)"},
+ {"-sz", argInt, &sz, 0,
+ "size of crop square in pixels (sets W and H)"},
+ {"-cropbox",argFlag, &useCropBox, 0,
+ "use the crop box rather than media box"},
+
+ {"-png", argFlag, &png, 0,
+ "generate a PNG file"},
+ {"-ps", argFlag, &ps, 0,
+ "generate PostScript file"},
+ {"-pdf", argFlag, &pdf, 0,
+ "generate a PDF file"},
+
+
+ {"-opw", argString, ownerPassword, sizeof(ownerPassword),
+ "owner password (for encrypted files)"},
+ {"-upw", argString, userPassword, sizeof(userPassword),
+ "user password (for encrypted files)"},
+
+ {"-q", argFlag, &quiet, 0,
+ "don't print any messages or errors"},
+ {"-v", argFlag, &printVersion, 0,
+ "print copyright and version info"},
+ {"-h", argFlag, &printHelp, 0,
+ "print usage information"},
+ {"-help", argFlag, &printHelp, 0,
+ "print usage information"},
+ {"--help", argFlag, &printHelp, 0,
+ "print usage information"},
+ {"-?", argFlag, &printHelp, 0,
+ "print usage information"},
+ {NULL}
+};
+
+
+static void create_surface(char *outFile, cairo_surface_t **surface_out,
+ GBool *printing_out)
+{
+ char file[OUT_FILE_SZ];
+
+ strcpy(file, outFile);
+ if (png) {
+ *surface_out = cairo_image_surface_create (CAIRO_FORMAT_ARGB32, 1, 1);
+ *printing_out = gFalse;
+ } else if (ps) {
+ strcat(file, ".ps");
+ *surface_out = cairo_ps_surface_create (file, w, h);
+ *printing_out = gTrue;
+ } else if (pdf) {
+ strcat(file, ".pdf");
+ *surface_out = cairo_pdf_surface_create (file, w, h);
+ *printing_out = gTrue;
+ }
+}
+
+static void start_page(cairo_surface_t **surface, int w, int h,
+ double x_res, double y_res, int rotate)
+{
+ if (png) {
+ cairo_surface_destroy(*surface);
+ *surface = cairo_image_surface_create (CAIRO_FORMAT_ARGB32, w*x_res/72.0,
h*y_res/72.0);
+ } else if (ps) {
+ cairo_ps_surface_set_size(*surface, w, h);
+ } else if (pdf) {
+ cairo_pdf_surface_set_size(*surface, w, h);
+ }
+}
+
+static void end_page(cairo_surface_t *surface, char *outFile)
+{
+ char file[OUT_FILE_SZ];
+
+ strcpy(file, outFile);
+ if (png) {
+ strcat(file, ".png");
+ cairo_surface_write_to_png (surface, file);
+ } else if (ps || pdf) {
+ cairo_surface_show_page(surface);
+ }
+}
+
+static int render_page(CairoOutputDev *output_dev, PDFDoc *doc,
+ cairo_surface_t *surface,
+ GBool printing, int pg,
+ int x, int y, int w, int h,
+ double pg_w, double pg_h,
+ double x_res, double y_res)
+{
+ cairo_t *cr;
+ cairo_status_t status;
+ TextPage *text = NULL;
+
+ 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);
+ h = (y+h > pg_h ? (int)ceil(pg_h-y) : h);
+
+ cr = cairo_create (surface);
+ cairo_save (cr);
+ output_dev->setCairo (cr);
+ output_dev->setPrinting (printing);
+
+ if (!printing)
+ cairo_scale (cr, x_res/72.0, y_res/72.0);
+
+ text = new TextPage(gFalse);
+ if (!printing)
+ output_dev->setTextPage (text);
+
+ /* NOTE: instead of passing -1 we should/could use cairo_clip_extents()
+ * to get a bounding box */
+ cairo_save (cr);
+ doc->displayPageSlice(output_dev, pg, /* page */
+ 72.0, 72.0, 0,
+ gFalse, /* useMediaBox */
+ !useCropBox, /* Crop */
+ printing,
+ x, y, w, h);
+ cairo_restore (cr);
+
+ output_dev->setCairo (NULL);
+ output_dev->setTextPage (NULL);
+
+ if (!printing) {
+ cairo_save (cr);
+ cairo_set_operator (cr, CAIRO_OPERATOR_DEST_OVER);
+ cairo_set_source_rgb (cr, 1, 1, 1);
+ cairo_paint (cr);
+ cairo_restore (cr);
+ }
+
+ status = cairo_status(cr);
+ if (status)
+ fprintf(stderr, "cairo error: %s\n", cairo_status_to_string (status));
+ cairo_destroy (cr);
+
+ if (text != NULL)
+ text->decRefCnt();
+
+ return 0;
+}
+
+int main(int argc, char *argv[]) {
+ PDFDoc *doc;
+ GooString *fileName = NULL;
+ char *outRoot;
+ char outFile[OUT_FILE_SZ];
+ GooString *ownerPW, *userPW;
+ GBool ok;
+ int exitCode;
+ int pg, pg_num_len;
+ double pg_w, pg_h, tmp;
+ char *p;
+ CairoOutputDev *output_dev;
+ cairo_surface_t *surface;
+ cairo_status_t status;
+ GBool printing;
+
+ exitCode = 99;
+
+ // parse args
+ ok = parseArgs(argDesc, &argc, argv);
+
+ if ( resolution != 0.0 &&
+ (x_resolution == 150.0 ||
+ y_resolution == 150.0)) {
+ x_resolution = resolution;
+ y_resolution = resolution;
+ }
+ if (!ok || argc < 2 || argc > 3 || printVersion || printHelp) {
+ fprintf(stderr, "pdftocairo version %s\n", PACKAGE_VERSION);
+ fprintf(stderr, "%s\n", popplerCopyright);
+ fprintf(stderr, "%s\n", xpdfCopyright);
+ if (!printVersion) {
+ printUsage("pdftocairo", "PDF-file [output-file]", argDesc);
+ }
+ goto err0;
+ }
+
+ if (!png && !ps && !pdf) {
+ fprintf(stderr, "One of -png, -ps, or -pdf must be specified\n");
+ goto err0;
+ }
+
+ fileName = new GooString(argv[1]);
+ if (argc == 3)
+ outRoot = strdup(argv[2]);
+ else
+ outRoot = strdup(argv[1]);
+
+ p = strrchr(outRoot, '.');
+ if (p)
+ *p = 0;
+
+ // read config file
+ globalParams = new GlobalParams();
+ if (quiet) {
+ globalParams->setErrQuiet(quiet);
+ }
+
+ // open PDF file
+ if (ownerPassword[0]) {
+ ownerPW = new GooString(ownerPassword);
+ } else {
+ ownerPW = NULL;
+ }
+ if (userPassword[0]) {
+ userPW = new GooString(userPassword);
+ } else {
+ userPW = NULL;
+ }
+ doc = new PDFDoc(fileName, ownerPW, userPW);
+ if (userPW) {
+ delete userPW;
+ }
+ if (ownerPW) {
+ delete ownerPW;
+ }
+ if (!doc->isOk()) {
+ exitCode = 1;
+ goto err1;
+ }
+
+ // get page range
+ if (firstPage < 1)
+ firstPage = 1;
+ if (lastPage < 1 || lastPage > doc->getNumPages())
+ lastPage = doc->getNumPages();
+
+ if (sz != 0)
+ w = h = sz;
+
+ create_surface(outRoot, &surface, &printing);
+ output_dev = new CairoOutputDev ();
+ output_dev->startDoc(doc->getXRef (), doc->getCatalog ());
+
+ pg_num_len = (int)ceil(log((double)doc->getNumPages()) / log((double)10));
+ for (pg = firstPage; pg <= lastPage; ++pg) {
+ if (useCropBox) {
+ pg_w = doc->getPageCropWidth(pg);
+ pg_h = doc->getPageCropHeight(pg);
+ } else {
+ pg_w = doc->getPageMediaWidth(pg);
+ pg_h = doc->getPageMediaHeight(pg);
+ }
+
+ if (scaleTo != 0) {
+ resolution = (72.0 * scaleTo) / (pg_w > pg_h ? pg_w : pg_h);
+ x_resolution = y_resolution = resolution;
+ } else {
+ if (x_scaleTo != 0) {
+ x_resolution = (72.0 * x_scaleTo) / pg_w;
+ }
+ if (y_scaleTo != 0) {
+ y_resolution = (72.0 * y_scaleTo) / pg_h;
+ }
+ }
+
+ start_page(&surface, pg_w, pg_h, x_resolution, y_resolution,
doc->getPageRotate(pg));
+ render_page(output_dev, doc, surface, printing, pg,
+ x, y, w, h, pg_w, pg_h, x_resolution, y_resolution);
+ snprintf(outFile, OUT_FILE_SZ, "%.*s-%0*d",
+ OUT_FILE_SZ - 32, outRoot, pg_num_len, pg);
+ end_page(surface, outFile);
+ }
+ cairo_surface_finish(surface);
+ status = cairo_surface_status(surface);
+ if (status)
+ fprintf(stderr, "cairo error: %s\n", cairo_status_to_string (status));
+ cairo_surface_destroy(surface);
+ delete output_dev;
+
+ exitCode = 0;
+
+ // clean up
+ err1:
+ delete doc;
+ delete globalParams;
+ err0:
+
+ // check for memory leaks
+ Object::memCheck(stderr);
+ gMemReport(stderr);
+
+ return exitCode;
+}
--
1.7.0.4
>From 3c1ca561e49d55dc5fab18333397815edb04ee29 Mon Sep 17 00:00:00 2001
From: Stefan Thomas <tho...@txtbear.com>
Date: Sat, 9 Jan 2010 17:08:11 +0000
Subject: [PATCH 2/6] pdftocairo: Added SVG support.
Simplified initialization code (necessary because there is no resize option for
Cairo SVG surfaces.)
---
utils/.gitignore | 1 +
utils/pdftocairo.cc | 49 +++++++++++++++++++++++--------------------------
2 files changed, 24 insertions(+), 26 deletions(-)
diff --git a/utils/.gitignore b/utils/.gitignore
index 696f074..a77622a 100644
--- a/utils/.gitignore
+++ b/utils/.gitignore
@@ -7,6 +7,7 @@ pdfimages
pdfinfo
pdftohtml
pdftoppm
+pdftocairo
pdftops
pdftotext
pdftoabw
diff --git a/utils/pdftocairo.cc b/utils/pdftocairo.cc
index 8540b42..2a8b6dc 100644
--- a/utils/pdftocairo.cc
+++ b/utils/pdftocairo.cc
@@ -32,6 +32,7 @@
#include <cairo.h>
#include <cairo-ps.h>
#include <cairo-pdf.h>
+#include <cairo-svg.h>
#include "parseargs.h"
#include "goo/gmem.h"
#include "goo/GooString.h"
@@ -59,6 +60,7 @@ static GBool useCropBox = gFalse;
static GBool png = gFalse;
static GBool ps = gFalse;
static GBool pdf = gFalse;
+static GBool svg = gFalse;
static char ownerPassword[33] = "";
static char userPassword[33] = "";
static GBool quiet = gFalse;
@@ -103,6 +105,8 @@ static const ArgDesc argDesc[] = {
"generate PostScript file"},
{"-pdf", argFlag, &pdf, 0,
"generate a PDF file"},
+ {"-svg", argFlag, &svg, 0,
+ "generate a SVG file"},
{"-opw", argString, ownerPassword, sizeof(ownerPassword),
@@ -126,37 +130,28 @@ static const ArgDesc argDesc[] = {
};
-static void create_surface(char *outFile, cairo_surface_t **surface_out,
- GBool *printing_out)
+static cairo_surface_t *start_page(char *outFile, int w, int h,
+ double x_res, double y_res, int rotate)
{
char file[OUT_FILE_SZ];
+ cairo_surface_t *surface;
strcpy(file, outFile);
+
if (png) {
- *surface_out = cairo_image_surface_create (CAIRO_FORMAT_ARGB32, 1, 1);
- *printing_out = gFalse;
+ surface = cairo_image_surface_create (CAIRO_FORMAT_ARGB32, w*x_res/72.0,
h*y_res/72.0);
} else if (ps) {
strcat(file, ".ps");
- *surface_out = cairo_ps_surface_create (file, w, h);
- *printing_out = gTrue;
+ surface = cairo_ps_surface_create (file, w, h);
} else if (pdf) {
strcat(file, ".pdf");
- *surface_out = cairo_pdf_surface_create (file, w, h);
- *printing_out = gTrue;
- }
-}
-
-static void start_page(cairo_surface_t **surface, int w, int h,
- double x_res, double y_res, int rotate)
-{
- if (png) {
- cairo_surface_destroy(*surface);
- *surface = cairo_image_surface_create (CAIRO_FORMAT_ARGB32, w*x_res/72.0,
h*y_res/72.0);
- } else if (ps) {
- cairo_ps_surface_set_size(*surface, w, h);
- } else if (pdf) {
- cairo_pdf_surface_set_size(*surface, w, h);
+ surface = cairo_pdf_surface_create (file, w, h);
+ } else if (svg) {
+ strcat(file, ".svg");
+ surface = cairo_svg_surface_create (file, w, h);
}
+
+ return surface;
}
static void end_page(cairo_surface_t *surface, char *outFile)
@@ -167,7 +162,7 @@ static void end_page(cairo_surface_t *surface, char
*outFile)
if (png) {
strcat(file, ".png");
cairo_surface_write_to_png (surface, file);
- } else if (ps || pdf) {
+ } else if (ps || pdf || svg) {
cairo_surface_show_page(surface);
}
}
@@ -270,8 +265,8 @@ int main(int argc, char *argv[]) {
goto err0;
}
- if (!png && !ps && !pdf) {
- fprintf(stderr, "One of -png, -ps, or -pdf must be specified\n");
+ if (!png && !ps && !pdf && !svg) {
+ fprintf(stderr, "One of -png, -ps, -pdf or -svg must be specified\n");
goto err0;
}
@@ -323,7 +318,6 @@ int main(int argc, char *argv[]) {
if (sz != 0)
w = h = sz;
- create_surface(outRoot, &surface, &printing);
output_dev = new CairoOutputDev ();
output_dev->startDoc(doc->getXRef (), doc->getCatalog ());
@@ -348,8 +342,11 @@ int main(int argc, char *argv[]) {
y_resolution = (72.0 * y_scaleTo) / pg_h;
}
}
+
+ // Enable printing mode for all output types except PNG
+ printing = (png) ? gFalse : gTrue;
- start_page(&surface, pg_w, pg_h, x_resolution, y_resolution,
doc->getPageRotate(pg));
+ surface = start_page(outRoot, pg_w, pg_h, x_resolution, y_resolution,
doc->getPageRotate(pg));
render_page(output_dev, doc, surface, printing, pg,
x, y, w, h, pg_w, pg_h, x_resolution, y_resolution);
snprintf(outFile, OUT_FILE_SZ, "%.*s-%0*d",
--
1.7.0.4
>From ca12ce32d7dc92114cf40891c7be9aaacae4d6ad Mon Sep 17 00:00:00 2001
From: Stefan Thomas <tho...@txtbear.com>
Date: Sat, 9 Jan 2010 17:11:45 +0000
Subject: [PATCH 3/6] pdftocairo: Code style; Removed spaces before parentheses
in function calls.
---
utils/pdftocairo.cc | 22 +++++++++++-----------
1 files changed, 11 insertions(+), 11 deletions(-)
diff --git a/utils/pdftocairo.cc b/utils/pdftocairo.cc
index 2a8b6dc..b13d5d2 100644
--- a/utils/pdftocairo.cc
+++ b/utils/pdftocairo.cc
@@ -204,17 +204,17 @@ static int render_page(CairoOutputDev *output_dev, PDFDoc
*doc,
!useCropBox, /* Crop */
printing,
x, y, w, h);
- cairo_restore (cr);
+ cairo_restore(cr);
- output_dev->setCairo (NULL);
- output_dev->setTextPage (NULL);
+ output_dev->setCairo(NULL);
+ output_dev->setTextPage(NULL);
if (!printing) {
- cairo_save (cr);
- cairo_set_operator (cr, CAIRO_OPERATOR_DEST_OVER);
- cairo_set_source_rgb (cr, 1, 1, 1);
- cairo_paint (cr);
- cairo_restore (cr);
+ cairo_save(cr);
+ cairo_set_operator(cr, CAIRO_OPERATOR_DEST_OVER);
+ cairo_set_source_rgb(cr, 1, 1, 1);
+ cairo_paint(cr);
+ cairo_restore(cr);
}
status = cairo_status(cr);
@@ -318,8 +318,8 @@ int main(int argc, char *argv[]) {
if (sz != 0)
w = h = sz;
- output_dev = new CairoOutputDev ();
- output_dev->startDoc(doc->getXRef (), doc->getCatalog ());
+ output_dev = new CairoOutputDev();
+ output_dev->startDoc(doc->getXRef(), doc->getCatalog());
pg_num_len = (int)ceil(log((double)doc->getNumPages()) / log((double)10));
for (pg = firstPage; pg <= lastPage; ++pg) {
@@ -356,7 +356,7 @@ int main(int argc, char *argv[]) {
cairo_surface_finish(surface);
status = cairo_surface_status(surface);
if (status)
- fprintf(stderr, "cairo error: %s\n", cairo_status_to_string (status));
+ fprintf(stderr, "cairo error: %s\n", cairo_status_to_string(status));
cairo_surface_destroy(surface);
delete output_dev;
--
1.7.0.4
>From e0a81209b6a86552eba385296fce389a8744d600 Mon Sep 17 00:00:00 2001
From: Stefan Thomas <tho...@txtbear.com>
Date: Sat, 9 Jan 2010 17:32:07 +0000
Subject: [PATCH 4/6] pdftocairo: Centralized output filename generation.
Nicer to have the filename generated in one place, also the filenames now all
have numbers, not just png.
---
utils/pdftocairo.cc | 58 ++++++++++++++++++++++++++++----------------------
1 files changed, 32 insertions(+), 26 deletions(-)
diff --git a/utils/pdftocairo.cc b/utils/pdftocairo.cc
index b13d5d2..9c4981f 100644
--- a/utils/pdftocairo.cc
+++ b/utils/pdftocairo.cc
@@ -130,25 +130,36 @@ static const ArgDesc argDesc[] = {
};
+static void format_output_filename(char *outFile, char *outRoot,
+ int pg_num_len, int pg)
+{
+ snprintf(outFile, OUT_FILE_SZ, "%.*s-%0*d",
+ OUT_FILE_SZ - 32, outRoot, pg_num_len, pg);
+
+ if (png) {
+ strcat(outFile, ".png");
+ } else if (ps) {
+ strcat(outFile, ".ps");
+ } else if (pdf) {
+ strcat(outFile, ".pdf");
+ } else if (svg) {
+ strcat(outFile, ".svg");
+ }
+}
+
static cairo_surface_t *start_page(char *outFile, int w, int h,
double x_res, double y_res, int rotate)
{
- char file[OUT_FILE_SZ];
cairo_surface_t *surface;
-
- strcpy(file, outFile);
if (png) {
- surface = cairo_image_surface_create (CAIRO_FORMAT_ARGB32, w*x_res/72.0,
h*y_res/72.0);
+ surface = cairo_image_surface_create(CAIRO_FORMAT_ARGB32, w*x_res/72.0,
h*y_res/72.0);
} else if (ps) {
- strcat(file, ".ps");
- surface = cairo_ps_surface_create (file, w, h);
+ surface = cairo_ps_surface_create(outFile, w, h);
} else if (pdf) {
- strcat(file, ".pdf");
- surface = cairo_pdf_surface_create (file, w, h);
+ surface = cairo_pdf_surface_create(outFile, w, h);
} else if (svg) {
- strcat(file, ".svg");
- surface = cairo_svg_surface_create (file, w, h);
+ surface = cairo_svg_surface_create(outFile, w, h);
}
return surface;
@@ -156,12 +167,8 @@ static cairo_surface_t *start_page(char *outFile, int w,
int h,
static void end_page(cairo_surface_t *surface, char *outFile)
{
- char file[OUT_FILE_SZ];
-
- strcpy(file, outFile);
if (png) {
- strcat(file, ".png");
- cairo_surface_write_to_png (surface, file);
+ cairo_surface_write_to_png(surface, outFile);
} else if (ps || pdf || svg) {
cairo_surface_show_page(surface);
}
@@ -231,7 +238,7 @@ static int render_page(CairoOutputDev *output_dev, PDFDoc
*doc,
int main(int argc, char *argv[]) {
PDFDoc *doc;
GooString *fileName = NULL;
- char *outRoot;
+ char *outRoot = NULL;
char outFile[OUT_FILE_SZ];
GooString *ownerPW, *userPW;
GBool ok;
@@ -270,15 +277,14 @@ int main(int argc, char *argv[]) {
goto err0;
}
- fileName = new GooString(argv[1]);
- if (argc == 3)
+ if (argc > 1) fileName = new GooString(argv[1]);
+ if (argc == 3) {
outRoot = strdup(argv[2]);
- else
- outRoot = strdup(argv[1]);
- p = strrchr(outRoot, '.');
- if (p)
- *p = 0;
+ p = strrchr(outRoot, '.');
+ if (p)
+ *p = 0;
+ }
// read config file
globalParams = new GlobalParams();
@@ -345,12 +351,12 @@ int main(int argc, char *argv[]) {
// Enable printing mode for all output types except PNG
printing = (png) ? gFalse : gTrue;
+
+ format_output_filename(outFile, outRoot, pg_num_len, pg);
- surface = start_page(outRoot, pg_w, pg_h, x_resolution, y_resolution,
doc->getPageRotate(pg));
+ surface = start_page(outFile, pg_w, pg_h, x_resolution, y_resolution,
doc->getPageRotate(pg));
render_page(output_dev, doc, surface, printing, pg,
x, y, w, h, pg_w, pg_h, x_resolution, y_resolution);
- snprintf(outFile, OUT_FILE_SZ, "%.*s-%0*d",
- OUT_FILE_SZ - 32, outRoot, pg_num_len, pg);
end_page(surface, outFile);
}
cairo_surface_finish(surface);
--
1.7.0.4
>From d85e99891c0089f2805362dbfae2e2372f668377 Mon Sep 17 00:00:00 2001
From: Stefan Thomas <tho...@txtbear.com>
Date: Tue, 13 Jul 2010 14:53:34 +0100
Subject: [PATCH 5/6] pdftocairo: Updated to use PDFDocFactory.
---
utils/pdftocairo.cc | 15 ++++++++++++++-
1 files changed, 14 insertions(+), 1 deletions(-)
diff --git a/utils/pdftocairo.cc b/utils/pdftocairo.cc
index 9c4981f..a832e8c 100644
--- a/utils/pdftocairo.cc
+++ b/utils/pdftocairo.cc
@@ -39,6 +39,7 @@
#include "GlobalParams.h"
#include "Object.h"
#include "PDFDoc.h"
+#include "PDFDocFactory.h"
#include "CairoOutputDev.h"
#define OUT_FILE_SZ 512
@@ -133,6 +134,8 @@ static const ArgDesc argDesc[] = {
static void format_output_filename(char *outFile, char *outRoot,
int pg_num_len, int pg)
{
+ if (!outRoot) outRoot = "cairoout";
+
snprintf(outFile, OUT_FILE_SZ, "%.*s-%0*d",
OUT_FILE_SZ - 32, outRoot, pg_num_len, pg);
@@ -303,7 +306,17 @@ int main(int argc, char *argv[]) {
} else {
userPW = NULL;
}
- doc = new PDFDoc(fileName, ownerPW, userPW);
+
+ if (fileName == NULL) {
+ fileName = new GooString("fd://0");
+ }
+ if (fileName->cmp("-") == 0) {
+ delete fileName;
+ fileName = new GooString("fd://0");
+ }
+ doc = PDFDocFactory().createPDFDoc(*fileName, ownerPW, userPW);
+ delete fileName;
+
if (userPW) {
delete userPW;
}
--
1.7.0.4
>From 185a860d64654a85bc31b60d2ceac162ed16de20 Mon Sep 17 00:00:00 2001
From: Stefan Thomas <tho...@txtbear.com>
Date: Thu, 15 Jul 2010 04:12:04 +0100
Subject: [PATCH 6/6] pdftocairo: Added -jpeg output option.
---
utils/pdftocairo.cc | 61 ++++++++++++++++++++++++++++++++++++++++++++++-----
1 files changed, 55 insertions(+), 6 deletions(-)
diff --git a/utils/pdftocairo.cc b/utils/pdftocairo.cc
index a832e8c..8e5db15 100644
--- a/utils/pdftocairo.cc
+++ b/utils/pdftocairo.cc
@@ -36,6 +36,7 @@
#include "parseargs.h"
#include "goo/gmem.h"
#include "goo/GooString.h"
+#include "goo/JpegWriter.h"
#include "GlobalParams.h"
#include "Object.h"
#include "PDFDoc.h"
@@ -59,6 +60,7 @@ static int h = 0;
static int sz = 0;
static GBool useCropBox = gFalse;
static GBool png = gFalse;
+static GBool jpg = gFalse;
static GBool ps = gFalse;
static GBool pdf = gFalse;
static GBool svg = gFalse;
@@ -102,11 +104,13 @@ static const ArgDesc argDesc[] = {
{"-png", argFlag, &png, 0,
"generate a PNG file"},
- {"-ps", argFlag, &ps, 0,
+ {"-jpeg", argFlag, &jpg, 0,
+ "generate a JPEG file"},
+ {"-ps", argFlag, &ps, 0,
"generate PostScript file"},
- {"-pdf", argFlag, &pdf, 0,
+ {"-pdf", argFlag, &pdf, 0,
"generate a PDF file"},
- {"-svg", argFlag, &svg, 0,
+ {"-svg", argFlag, &svg, 0,
"generate a SVG file"},
@@ -141,6 +145,8 @@ static void format_output_filename(char *outFile, char
*outRoot,
if (png) {
strcat(outFile, ".png");
+ } else if (jpg) {
+ strcat(outFile, ".jpg");
} else if (ps) {
strcat(outFile, ".ps");
} else if (pdf) {
@@ -157,6 +163,8 @@ static cairo_surface_t *start_page(char *outFile, int w,
int h,
if (png) {
surface = cairo_image_surface_create(CAIRO_FORMAT_ARGB32, w*x_res/72.0,
h*y_res/72.0);
+ } else if (jpg) {
+ surface = cairo_image_surface_create(CAIRO_FORMAT_RGB24, w*x_res/72.0,
h*y_res/72.0);
} else if (ps) {
surface = cairo_ps_surface_create(outFile, w, h);
} else if (pdf) {
@@ -168,10 +176,43 @@ static cairo_surface_t *start_page(char *outFile, int w,
int h,
return surface;
}
+static void end_page_jpeg(cairo_surface_t *surface, char *outFile)
+{
+ unsigned char *p;
+ int width, height, stride, i, j;
+ FILE *f;
+ JpegWriter *writer;
+ unsigned char *row;
+
+ width = cairo_image_surface_get_width(surface);
+ height = cairo_image_surface_get_height(surface);
+ stride = cairo_image_surface_get_stride(surface);
+ p = cairo_image_surface_get_data(surface);
+
+ f = fopen(outFile, "w");
+ writer = new JpegWriter();
+ writer->init(f, width, height, 72, 72);
+
+ row = new unsigned char[3 * width];
+ for (i = 0; i < height; i++) {
+ for (j = 0; j < width; j++) {
+ row[3*j] = p[j * 4 + 2];
+ row[3*j+1] = p[j * 4 + 1];
+ row[3*j+2] = p[j * 4];
+ }
+
+ writer->writeRow(&row);
+ p += stride;
+ }
+ writer->close();
+}
+
static void end_page(cairo_surface_t *surface, char *outFile)
{
if (png) {
cairo_surface_write_to_png(surface, outFile);
+ } else if (jpg) {
+ end_page_jpeg(surface, outFile);
} else if (ps || pdf || svg) {
cairo_surface_show_page(surface);
}
@@ -194,6 +235,7 @@ static int render_page(CairoOutputDev *output_dev, PDFDoc
*doc,
h = (y+h > pg_h ? (int)ceil(pg_h-y) : h);
cr = cairo_create (surface);
+
cairo_save (cr);
output_dev->setCairo (cr);
output_dev->setPrinting (printing);
@@ -201,6 +243,13 @@ static int render_page(CairoOutputDev *output_dev, PDFDoc
*doc,
if (!printing)
cairo_scale (cr, x_res/72.0, y_res/72.0);
+ // JPEGs are non-transparent, so we need a white background
+ if (jpg) {
+ cairo_rectangle(cr, 0, 0, w, h);
+ cairo_set_source_rgb(cr, 1, 1, 1);
+ cairo_fill(cr);
+ }
+
text = new TextPage(gFalse);
if (!printing)
output_dev->setTextPage (text);
@@ -275,8 +324,8 @@ int main(int argc, char *argv[]) {
goto err0;
}
- if (!png && !ps && !pdf && !svg) {
- fprintf(stderr, "One of -png, -ps, -pdf or -svg must be specified\n");
+ if (!png && !jpg && !ps && !pdf && !svg) {
+ fprintf(stderr, "One of -png, -jpeg, -ps, -pdf or -svg must be
specified\n");
goto err0;
}
@@ -363,7 +412,7 @@ int main(int argc, char *argv[]) {
}
// Enable printing mode for all output types except PNG
- printing = (png) ? gFalse : gTrue;
+ printing = (png || jpg) ? gFalse : gTrue;
format_output_filename(outFile, outRoot, pg_num_len, pg);
--
1.7.0.4
_______________________________________________
poppler mailing list
poppler@lists.freedesktop.org
http://lists.freedesktop.org/mailman/listinfo/poppler