From 98f1da63108f8ed363ad18f1b67e9f70552be925 Mon Sep 17 00:00:00 2001 From: Adrian Johnson Date: Sun, 16 Jul 2017 12:23:28 +0930 Subject: [PATCH 2/2] pdftoppm: add -jpegopt for setting jpeg compression parameters Bug 45727 --- splash/SplashBitmap.cc | 11 ++++++++ splash/SplashBitmap.h | 10 ++++++++ utils/pdftoppm.1 | 15 +++++++++++ utils/pdftoppm.cc | 68 +++++++++++++++++++++++++++++++++++++++++++++++++- 4 files changed, 103 insertions(+), 1 deletion(-) diff --git a/splash/SplashBitmap.cc b/splash/SplashBitmap.cc index e9b2be42..75fc45fa 100644 --- a/splash/SplashBitmap.cc +++ b/splash/SplashBitmap.cc @@ -351,6 +351,15 @@ SplashError SplashBitmap::writeImgFile(SplashImageFileFormat format, char *fileN return e; } +void SplashBitmap::setJpegParams(ImgWriter *writer) +{ +#ifdef ENABLE_LIBJPEG + static_cast(writer)->setProgressive(jpegProgressive); + if (jpegQuality >= 0) + static_cast(writer)->setQuality(jpegQuality); +#endif +} + SplashError SplashBitmap::writeImgFile(SplashImageFileFormat format, FILE *f, int hDPI, int vDPI, const char *compressionString) { ImgWriter *writer; SplashError e; @@ -368,10 +377,12 @@ SplashError SplashBitmap::writeImgFile(SplashImageFileFormat format, FILE *f, in #if SPLASH_CMYK case splashFormatJpegCMYK: writer = new JpegWriter(JpegWriter::CMYK); + setJpegParams(writer); break; #endif case splashFormatJpeg: writer = new JpegWriter(); + setJpegParams(writer); break; #endif diff --git a/splash/SplashBitmap.h b/splash/SplashBitmap.h index 6858f90f..42391020 100644 --- a/splash/SplashBitmap.h +++ b/splash/SplashBitmap.h @@ -69,6 +69,10 @@ public: Guchar *getAlphaPtr() { return alpha; } GooList *getSeparationList() { return separationList; } + // JPEG Compression parameters + void setJpegQuality(int quality) { jpegQuality = quality; } + void setJpegProgressive(GBool progressive) { jpegProgressive = progressive; } + SplashError writePNMFile(char *fileName); SplashError writePNMFile(FILE *f); SplashError writeAlphaPGMFile(char *fileName); @@ -111,7 +115,13 @@ private: // (always top-down) GooList *separationList; // list of spot colorants and their mapping functions + // JPEG Compression parameters + int jpegQuality = -1; + GBool jpegProgressive = gFalse; + friend class Splash; + + void setJpegParams(ImgWriter *writer); }; #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 "=[,=]". 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..df9002ab 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 =[,=]*"}, #endif #if SPLASH_CMYK {"-overprint",argFlag, &overprint, 0, @@ -208,6 +213,58 @@ static const ArgDesc argDesc[] = { {NULL} }; +static GBool parseJpegOptions() +{ + //jpegOpt format is: =,=,... + 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 "= " + 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 "" and value is "" + + 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,7 +282,10 @@ static void savePageSlice(PDFDoc *doc, ); SplashBitmap *bitmap = splashOut->getBitmap(); - + + bitmap->setJpegQuality(jpegQuality); + bitmap->setJpegProgressive(jpegProgressive); + if (ppmFile != NULL) { if (png) { bitmap->writeImgFile(splashFormatPng, ppmFile, x_resolution, y_resolution); @@ -372,6 +432,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]) { -- 2.11.0