[poppler] 2 commits - goo/JpegWriter.cc goo/JpegWriter.h splash/SplashBitmap.cc splash/SplashBitmap.h utils/pdftocairo.1 utils/pdftocairo.cc utils/pdftoppm.1 utils/pdftoppm.cc
Adrian Johnson
ajohnson at kemper.freedesktop.org
Wed Aug 16 21:32:00 UTC 2017
goo/JpegWriter.cc | 10 ++++++
goo/JpegWriter.h | 2 +
splash/SplashBitmap.cc | 25 +++++++++++----
splash/SplashBitmap.h | 15 +++++++--
utils/pdftocairo.1 | 17 +++++++++-
utils/pdftocairo.cc | 71 +++++++++++++++++++++++++++++++++++++++++++
utils/pdftoppm.1 | 15 +++++++++
utils/pdftoppm.cc | 80 +++++++++++++++++++++++++++++++++++++++++++++----
8 files changed, 219 insertions(+), 16 deletions(-)
New commits:
commit b9030a069756c84669ed6f408399cc7e2ce4fd10
Author: Adrian Johnson <ajohnson at redneon.com>
Date: Sun Jul 16 12:23:28 2017 +0930
pdftoppm: add -jpegopt for setting jpeg compression parameters
Bug 45727
diff --git a/splash/SplashBitmap.cc b/splash/SplashBitmap.cc
index e9b2be42..aae87025 100644
--- a/splash/SplashBitmap.cc
+++ b/splash/SplashBitmap.cc
@@ -337,7 +337,7 @@ SplashColorPtr SplashBitmap::takeData() {
return data2;
}
-SplashError SplashBitmap::writeImgFile(SplashImageFileFormat format, char *fileName, int hDPI, int vDPI, const char *compressionString) {
+SplashError SplashBitmap::writeImgFile(SplashImageFileFormat format, char *fileName, int hDPI, int vDPI, WriteImgParams* params) {
FILE *f;
SplashError e;
@@ -345,13 +345,24 @@ SplashError SplashBitmap::writeImgFile(SplashImageFileFormat format, char *fileN
return splashErrOpenFile;
}
- e = writeImgFile(format, f, hDPI, vDPI, compressionString);
-
+ e = writeImgFile(format, f, hDPI, vDPI, params);
+
fclose(f);
return e;
}
-SplashError SplashBitmap::writeImgFile(SplashImageFileFormat format, FILE *f, int hDPI, int vDPI, const char *compressionString) {
+void SplashBitmap::setJpegParams(ImgWriter *writer, WriteImgParams* params)
+{
+#ifdef ENABLE_LIBJPEG
+ if (params) {
+ static_cast<JpegWriter*>(writer)->setProgressive(params->jpegProgressive);
+ if (params->jpegQuality >= 0)
+ static_cast<JpegWriter*>(writer)->setQuality(params->jpegQuality);
+ }
+#endif
+}
+
+SplashError SplashBitmap::writeImgFile(SplashImageFileFormat format, FILE *f, int hDPI, int vDPI, WriteImgParams* params) {
ImgWriter *writer;
SplashError e;
@@ -368,10 +379,12 @@ SplashError SplashBitmap::writeImgFile(SplashImageFileFormat format, FILE *f, in
#if SPLASH_CMYK
case splashFormatJpegCMYK:
writer = new JpegWriter(JpegWriter::CMYK);
+ setJpegParams(writer, params);
break;
#endif
case splashFormatJpeg:
writer = new JpegWriter();
+ setJpegParams(writer, params);
break;
#endif
@@ -400,8 +413,8 @@ SplashError SplashBitmap::writeImgFile(SplashImageFileFormat format, FILE *f, in
fprintf(stderr, "TiffWriter: Mode %d not supported\n", mode);
writer = new TiffWriter();
}
- if (writer) {
- ((TiffWriter *)writer)->setCompressionString(compressionString);
+ if (writer && params) {
+ ((TiffWriter *)writer)->setCompressionString(params->tiffCompression.getCString());
}
break;
#endif
diff --git a/splash/SplashBitmap.h b/splash/SplashBitmap.h
index 6858f90f..9802bd30 100644
--- a/splash/SplashBitmap.h
+++ b/splash/SplashBitmap.h
@@ -72,9 +72,16 @@ public:
SplashError writePNMFile(char *fileName);
SplashError writePNMFile(FILE *f);
SplashError writeAlphaPGMFile(char *fileName);
-
- SplashError writeImgFile(SplashImageFileFormat format, char *fileName, int hDPI, int vDPI, const char *compressionString = "");
- SplashError writeImgFile(SplashImageFileFormat format, FILE *f, int hDPI, int vDPI, const char *compressionString = "");
+
+ struct WriteImgParams
+ {
+ int jpegQuality = -1;
+ GBool jpegProgressive = gFalse;
+ GooString tiffCompression;
+ };
+
+ SplashError writeImgFile(SplashImageFileFormat format, char *fileName, int hDPI, int vDPI, WriteImgParams* params = nullptr);
+ SplashError writeImgFile(SplashImageFileFormat format, FILE *f, int hDPI, int vDPI, WriteImgParams* params = nullptr);
SplashError writeImgFile(ImgWriter *writer, FILE *f, int hDPI, int vDPI, SplashColorMode imageWriterFormat);
enum ConversionMode
@@ -112,6 +119,8 @@ private:
GooList *separationList; // list of spot colorants and their mapping functions
friend class Splash;
+
+ void setJpegParams(ImgWriter *writer, WriteImgParams* params);
};
#endif
diff --git a/utils/pdftoppm.1 b/utils/pdftoppm.1
index e16ca7d9..b489e025 100644
--- a/utils/pdftoppm.1
+++ b/utils/pdftoppm.1
@@ -92,6 +92,11 @@ Generates a PNG file instead a PPM file.
.B \-jpeg
Generates a JPEG file instead a PPM file.
.TP
+.BI \-jpegopt " jpeg-options"
+When used with \-jpeg, takes a list of options to control the jpeg compression. See
+.B JPEG OPTIONS
+for the available options.
+.TP
.B \-tiff
Generates a TIFF file instead a PPM file.
.TP
@@ -156,6 +161,16 @@ Error related to PDF permissions.
.TP
99
Other error.
+.SH JPEG OPTIONS
+When JPEG output is specified, the \-jpegopt option can be used to control the JPEG compression parameters.
+It takes a string of the form "<opt>=<val>[,<opt>=<val>]". Currently the available options are:
+.TP
+.BI quality
+Selects the JPEG quality value. The value must be an integer between 0 and 100.
+.TP
+.BI progressive
+Select progressive JPEG output. The possible values are "y", "n",
+indicating progressive (yes) or non-progressive (no), respectively.
.SH AUTHOR
The pdftoppm software and documentation are copyright 1996-2011 Glyph
& Cog, LLC.
diff --git a/utils/pdftoppm.cc b/utils/pdftoppm.cc
index 3574595b..8da5327b 100644
--- a/utils/pdftoppm.cc
+++ b/utils/pdftoppm.cc
@@ -87,6 +87,9 @@ static GBool png = gFalse;
static GBool jpeg = gFalse;
static GBool jpegcmyk = gFalse;
static GBool tiff = gFalse;
+static GooString jpegOpt;
+static int jpegQuality = -1;
+static bool jpegProgressive = false;
#if SPLASH_CMYK
static GBool overprint = gFalse;
#endif
@@ -160,6 +163,8 @@ static const ArgDesc argDesc[] = {
{"-jpegcmyk",argFlag, &jpegcmyk, 0,
"generate a CMYK JPEG file"},
#endif
+ {"-jpegopt", argGooString, &jpegOpt, 0,
+ "jpeg options, with format <opt1>=<val1>[,<optN>=<valN>]*"},
#endif
#if SPLASH_CMYK
{"-overprint",argFlag, &overprint, 0,
@@ -208,6 +213,58 @@ static const ArgDesc argDesc[] = {
{NULL}
};
+static GBool parseJpegOptions()
+{
+ //jpegOpt format is: <opt1>=<val1>,<opt2>=<val2>,...
+ const char *nextOpt = jpegOpt.getCString();
+ while (nextOpt && *nextOpt)
+ {
+ const char *comma = strchr(nextOpt, ',');
+ GooString opt;
+ if (comma) {
+ opt.Set(nextOpt, comma - nextOpt);
+ nextOpt = comma + 1;
+ } else {
+ opt.Set(nextOpt);
+ nextOpt = NULL;
+ }
+ //here opt is "<optN>=<valN> "
+ const char *equal = strchr(opt.getCString(), '=');
+ if (!equal) {
+ fprintf(stderr, "Unknown jpeg option \"%s\"\n", opt.getCString());
+ return gFalse;
+ }
+ int iequal = equal - opt.getCString();
+ GooString value(&opt, iequal + 1, opt.getLength() - iequal - 1);
+ opt.del(iequal, opt.getLength() - iequal);
+ //here opt is "<optN>" and value is "<valN>"
+
+ if (opt.cmp("quality") == 0) {
+ if (!isInt(value.getCString())) {
+ fprintf(stderr, "Invalid jpeg quality\n");
+ return gFalse;
+ }
+ jpegQuality = atoi(value.getCString());
+ if (jpegQuality < 0 || jpegQuality > 100) {
+ fprintf(stderr, "jpeg quality must be between 0 and 100\n");
+ return gFalse;
+ }
+ } else if (opt.cmp("progressive") == 0) {
+ jpegProgressive = gFalse;
+ if (value.cmp("y") == 0) {
+ jpegProgressive = gTrue;
+ } else if (value.cmp("n") != 0) {
+ fprintf(stderr, "jpeg progressive option must be \"y\" or \"n\"\n");
+ return gFalse;
+ }
+ } else {
+ fprintf(stderr, "Unknown jpeg option \"%s\"\n", opt.getCString());
+ return gFalse;
+ }
+ }
+ return gTrue;
+}
+
static void savePageSlice(PDFDoc *doc,
SplashOutputDev *splashOut,
int pg, int x, int y, int w, int h,
@@ -225,16 +282,21 @@ static void savePageSlice(PDFDoc *doc,
);
SplashBitmap *bitmap = splashOut->getBitmap();
-
+
+ SplashBitmap::WriteImgParams params;
+ params.jpegQuality = jpegQuality;
+ params.jpegProgressive = jpegProgressive;
+ params.tiffCompression.Set(TiffCompressionStr);
+
if (ppmFile != NULL) {
if (png) {
bitmap->writeImgFile(splashFormatPng, ppmFile, x_resolution, y_resolution);
} else if (jpeg) {
- bitmap->writeImgFile(splashFormatJpeg, ppmFile, x_resolution, y_resolution);
+ bitmap->writeImgFile(splashFormatJpeg, ppmFile, x_resolution, y_resolution, ¶ms);
} else if (jpegcmyk) {
- bitmap->writeImgFile(splashFormatJpegCMYK, ppmFile, x_resolution, y_resolution);
+ bitmap->writeImgFile(splashFormatJpegCMYK, ppmFile, x_resolution, y_resolution, ¶ms);
} else if (tiff) {
- bitmap->writeImgFile(splashFormatTiff, ppmFile, x_resolution, y_resolution, TiffCompressionStr);
+ bitmap->writeImgFile(splashFormatTiff, ppmFile, x_resolution, y_resolution, ¶ms);
} else {
bitmap->writePNMFile(ppmFile);
}
@@ -246,9 +308,9 @@ static void savePageSlice(PDFDoc *doc,
if (png) {
bitmap->writeImgFile(splashFormatPng, stdout, x_resolution, y_resolution);
} else if (jpeg) {
- bitmap->writeImgFile(splashFormatJpeg, stdout, x_resolution, y_resolution);
+ bitmap->writeImgFile(splashFormatJpeg, stdout, x_resolution, y_resolution, ¶ms);
} else if (tiff) {
- bitmap->writeImgFile(splashFormatTiff, stdout, x_resolution, y_resolution, TiffCompressionStr);
+ bitmap->writeImgFile(splashFormatTiff, stdout, x_resolution, y_resolution, ¶ms);
} else {
bitmap->writePNMFile(stdout);
}
@@ -372,6 +434,12 @@ int main(int argc, char *argv[]) {
}
}
+ if (jpegOpt.getLength() > 0) {
+ if (!jpeg)
+ fprintf(stderr, "Warning: -jpegopt only valid with jpeg output.\n");
+ parseJpegOptions();
+ }
+
// read config file
globalParams = new GlobalParams();
if (enableFreeTypeStr[0]) {
commit dd54243f00557e84dba887403912d12463c8b1e9
Author: Adrian Johnson <ajohnson at redneon.com>
Date: Sat Jul 15 21:26:29 2017 +0930
pdftocairo: add -jpegopt for setting jpeg compression parameters
Bug 45727
diff --git a/goo/JpegWriter.cc b/goo/JpegWriter.cc
index 9b7c5051..a9959f09 100644
--- a/goo/JpegWriter.cc
+++ b/goo/JpegWriter.cc
@@ -64,6 +64,16 @@ JpegWriter::~JpegWriter()
delete priv;
}
+void JpegWriter::setQuality(int quality)
+{
+ priv->quality = quality;
+}
+
+void JpegWriter::setProgressive(bool progressive)
+{
+ priv->progressive = progressive;
+}
+
bool JpegWriter::init(FILE *f, int width, int height, int hDPI, int vDPI)
{
// Setup error handler
diff --git a/goo/JpegWriter.h b/goo/JpegWriter.h
index 7d0cf58e..aa3fb622 100644
--- a/goo/JpegWriter.h
+++ b/goo/JpegWriter.h
@@ -39,6 +39,8 @@ public:
JpegWriter(Format format = RGB);
~JpegWriter();
+ void setQuality(int quality);
+ void setProgressive(bool progressive);
bool init(FILE *f, int width, int height, int hDPI, int vDPI) override;
bool writePointers(unsigned char **rowPointers, int rowCount) override;
diff --git a/utils/pdftocairo.1 b/utils/pdftocairo.1
index 997093c1..3a60b73e 100644
--- a/utils/pdftocairo.1
+++ b/utils/pdftocairo.1
@@ -75,7 +75,7 @@ at the top left (SVG) or bottom left (PDF, PS, EPS).
Generates a PNG file(s)
.TP
.BI \-jpeg
-Generates a JPEG file(s)
+Generates a JPEG file(s). See also \-jpegopt.
.TP
.BI \-tiff
Generates a TIFF file(s)
@@ -199,6 +199,11 @@ Use a transparent page color instead of white (PNG and TIFF only).
.BI \-icc " icc-file"
Use the specified ICC file as the output profile (PNG only). The profile will be embedded in the PNG file.
.TP
+.BI \-jpegopt " jpeg-options"
+When used with \-jpeg, takes a list of options to control the jpeg compression. See
+.B JPEG OPTIONS
+for the available options.
+.TP
.B \-level2
Generate Level 2 PostScript (PS only).
.TP
@@ -295,6 +300,16 @@ Error related to ICC profile.
.TP
99
Other error.
+.SH JPEG OPTIONS
+When JPEG output is specified, the \-jpegopt option can be used to control the JPEG compression parameters.
+It takes a string of the form "<opt>=<val>[,<opt>=<val>]". Currently the available options are:
+.TP
+.BI quality
+Selects the JPEG quality value. The value must be an integer between 0 and 100.
+.TP
+.BI progressive
+Select progressive JPEG output. The possible values are "y", "n",
+indicating progressive (yes) or non-progressive (no), respectively.
.SH WINDOWS PRINTER OPTIONS
In Windows, you can use the \-print option to print directly to a system printer. Additionally, you can use the \-printopt
option to configure the printer. It takes a string of the form "<opt>=<val>[,<opt>=<val>]". Currently the available options are:
diff --git a/utils/pdftocairo.cc b/utils/pdftocairo.cc
index 91b77a55..9aacfb8d 100644
--- a/utils/pdftocairo.cc
+++ b/utils/pdftocairo.cc
@@ -128,6 +128,10 @@ static GBool quiet = gFalse;
static GBool printVersion = gFalse;
static GBool printHelp = gFalse;
+static GooString jpegOpt;
+static int jpegQuality = -1;
+static bool jpegProgressive = false;
+
static GooString printer;
static GooString printOpt;
#ifdef CAIRO_HAS_WIN32_SURFACE
@@ -142,6 +146,8 @@ static const ArgDesc argDesc[] = {
#if ENABLE_LIBJPEG
{"-jpeg", argFlag, &jpeg, 0,
"generate a JPEG file"},
+ {"-jpegopt", argGooString, &jpegOpt, 0,
+ "jpeg options, with format <opt1>=<val1>[,<optN>=<valN>]*"},
#endif
#if ENABLE_LIBTIFF
{"-tiff", argFlag, &tiff, 0,
@@ -321,6 +327,58 @@ static GBool parseAntialiasOption(GooString *antialias, cairo_antialias_t *antia
return gFalse;
}
+static GBool parseJpegOptions()
+{
+ //jpegOpt format is: <opt1>=<val1>,<opt2>=<val2>,...
+ const char *nextOpt = jpegOpt.getCString();
+ while (nextOpt && *nextOpt)
+ {
+ const char *comma = strchr(nextOpt, ',');
+ GooString opt;
+ if (comma) {
+ opt.Set(nextOpt, comma - nextOpt);
+ nextOpt = comma + 1;
+ } else {
+ opt.Set(nextOpt);
+ nextOpt = NULL;
+ }
+ //here opt is "<optN>=<valN> "
+ const char *equal = strchr(opt.getCString(), '=');
+ if (!equal) {
+ fprintf(stderr, "Unknown jpeg option \"%s\"\n", opt.getCString());
+ return gFalse;
+ }
+ int iequal = equal - opt.getCString();
+ GooString value(&opt, iequal + 1, opt.getLength() - iequal - 1);
+ opt.del(iequal, opt.getLength() - iequal);
+ //here opt is "<optN>" and value is "<valN>"
+
+ if (opt.cmp("quality") == 0) {
+ if (!isInt(value.getCString())) {
+ fprintf(stderr, "Invalid jpeg quality\n");
+ return gFalse;
+ }
+ jpegQuality = atoi(value.getCString());
+ if (jpegQuality < 0 || jpegQuality > 100) {
+ fprintf(stderr, "jpeg quality must be between 0 and 100\n");
+ return gFalse;
+ }
+ } else if (opt.cmp("progressive") == 0) {
+ jpegProgressive = gFalse;
+ if (value.cmp("y") == 0) {
+ jpegProgressive = gTrue;
+ } else if (value.cmp("n") != 0) {
+ fprintf(stderr, "jpeg progressive option must be \"y\" or \"n\"\n");
+ return gFalse;
+ }
+ } else {
+ fprintf(stderr, "Unknown jpeg option \"%s\"\n", opt.getCString());
+ return gFalse;
+ }
+ }
+ return gTrue;
+}
+
static void writePageImage(GooString *filename)
{
ImgWriter *writer = 0;
@@ -365,6 +423,10 @@ static void writePageImage(GooString *filename)
writer = new JpegWriter(JpegWriter::GRAY);
else
writer = new JpegWriter(JpegWriter::RGB);
+
+ static_cast<JpegWriter*>(writer)->setProgressive(jpegProgressive);
+ if (jpegQuality >= 0)
+ static_cast<JpegWriter*>(writer)->setQuality(jpegQuality);
#endif
} else if (tiff) {
#if ENABLE_LIBTIFF
@@ -979,6 +1041,15 @@ int main(int argc, char *argv[]) {
exit(99);
}
+ if (jpegOpt.getLength() > 0) {
+ if (!jpeg) {
+ fprintf(stderr, "Error: -jpegopt may only be used with jpeg output.\n");
+ exit(99);
+ }
+ if (!parseJpegOptions())
+ exit(99);
+ }
+
if (strlen(tiffCompressionStr) > 0 && !tiff) {
fprintf(stderr, "Error: -tiffcompression may only be used with tiff output.\n");
exit(99);
More information about the poppler
mailing list