From 732f55f5ce0a056e9ab805dc00877e36af796b80 Mon Sep 17 00:00:00 2001 From: Adrian Johnson Date: Sat, 15 Jul 2017 21:26:29 +0930 Subject: [PATCH 1/2] pdftocairo: add -jpegopt for setting jpeg compression parameters Bug 45727 --- goo/JpegWriter.cc | 10 ++++++++ goo/JpegWriter.h | 2 ++ utils/pdftocairo.1 | 17 ++++++++++++- utils/pdftocairo.cc | 71 +++++++++++++++++++++++++++++++++++++++++++++++++++++ 4 files changed, 99 insertions(+), 1 deletion(-) 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 "=[,=]". 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 "=[,=]". 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 =[,=]*"}, #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: =,=,... + 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 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(writer)->setProgressive(jpegProgressive); + if (jpegQuality >= 0) + static_cast(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); -- 2.11.0