1//========================================================================
2//
3// pdfimages.cc
4//
5// Copyright 1998-2003 Glyph & Cog, LLC
6//
7// Modified for Debian by Hamish Moffatt, 22 May 2002.
8//
9//========================================================================
10
11//========================================================================
12//
13// Modified under the Poppler project - http://poppler.freedesktop.org
14//
15// All changes made under the Poppler project to this file are licensed
16// under GPL version 2 or later
17//
18// Copyright (C) 2007-2008, 2010, 2018, 2022, 2024 Albert Astals Cid <aacid@kde.org>
19// Copyright (C) 2010 Hib Eris <hib@hiberis.nl>
20// Copyright (C) 2010 Jakob Voss <jakob.voss@gbv.de>
21// Copyright (C) 2012, 2013, 2017 Adrian Johnson <ajohnson@redneon.com>
22// Copyright (C) 2013 Suzuki Toshiya <mpsuzuki@hiroshima-u.ac.jp>
23// Copyright (C) 2018 Adam Reichold <adam.reichold@t-online.de>
24// Copyright (C) 2019, 2021 Oliver Sander <oliver.sander@tu-dresden.de>
25// Copyright (C) 2019 Hartmut Goebel <h.goebel@crazy-compilers.com>
26// Copyright (C) 2024 Fernando Herrera <fherrera@onirica.com>
27// Copyright (C) 2024 Sebastian J. Bronner <waschtl@sbronner.com>
28//
29// To see a description of the changes please see the Changelog file that
30// came with your tarball or type make ChangeLog if you are building from git
31//
32//========================================================================
33
34#include "config.h"
35#include <poppler-config.h>
36#include <cstdio>
37#include <cstdlib>
38#include <cstddef>
39#include <cstring>
40#include "parseargs.h"
41#include "goo/GooString.h"
42#include "goo/gmem.h"
43#include "GlobalParams.h"
44#include "Object.h"
45#include "Stream.h"
46#include "Array.h"
47#include "Dict.h"
48#include "XRef.h"
49#include "Catalog.h"
50#include "Page.h"
51#include "PDFDoc.h"
52#include "PDFDocFactory.h"
53#include "ImageOutputDev.h"
54#include "Error.h"
55#include "Win32Console.h"
56
57static int firstPage = 1;
58static int lastPage = 0;
59static bool listImages = false;
60static bool enablePNG = false;
61static bool enableTiff = false;
62static bool dumpJPEG = false;
63static bool dumpJP2 = false;
64static bool dumpJBIG2 = false;
65static bool dumpCCITT = false;
66static bool allFormats = false;
67static bool pageNames = false;
68static bool printFilenames = false;
69static char ownerPassword[33] = "\001";
70static char userPassword[33] = "\001";
71static bool quiet = false;
72static bool printVersion = false;
73static bool printHelp = false;
74
75static const ArgDesc argDesc[] = { { .arg: "-f", .kind: argInt, .val: &firstPage, .size: 0, .usage: "first page to convert" },
76 { .arg: "-l", .kind: argInt, .val: &lastPage, .size: 0, .usage: "last page to convert" },
77#ifdef ENABLE_LIBPNG
78 { .arg: "-png", .kind: argFlag, .val: &enablePNG, .size: 0, .usage: "change the default output format to PNG" },
79#endif
80#ifdef ENABLE_LIBTIFF
81 { .arg: "-tiff", .kind: argFlag, .val: &enableTiff, .size: 0, .usage: "change the default output format to TIFF" },
82#endif
83 { .arg: "-j", .kind: argFlag, .val: &dumpJPEG, .size: 0, .usage: "write JPEG images as JPEG files" },
84 { .arg: "-jp2", .kind: argFlag, .val: &dumpJP2, .size: 0, .usage: "write JPEG2000 images as JP2 files" },
85 { .arg: "-jbig2", .kind: argFlag, .val: &dumpJBIG2, .size: 0, .usage: "write JBIG2 images as JBIG2 files" },
86 { .arg: "-ccitt", .kind: argFlag, .val: &dumpCCITT, .size: 0, .usage: "write CCITT images as CCITT files" },
87 { .arg: "-all", .kind: argFlag, .val: &allFormats, .size: 0, .usage: "equivalent to -png -tiff -j -jp2 -jbig2 -ccitt" },
88 { .arg: "-list", .kind: argFlag, .val: &listImages, .size: 0, .usage: "print list of images instead of saving" },
89 { .arg: "-opw", .kind: argString, .val: ownerPassword, .size: sizeof(ownerPassword), .usage: "owner password (for encrypted files)" },
90 { .arg: "-upw", .kind: argString, .val: userPassword, .size: sizeof(userPassword), .usage: "user password (for encrypted files)" },
91 { .arg: "-p", .kind: argFlag, .val: &pageNames, .size: 0, .usage: "include page numbers in output file names" },
92 { .arg: "-print-filenames", .kind: argFlag, .val: &printFilenames, .size: 0, .usage: "print image filenames to stdout" },
93 { .arg: "-q", .kind: argFlag, .val: &quiet, .size: 0, .usage: "don't print any messages or errors" },
94 { .arg: "-v", .kind: argFlag, .val: &printVersion, .size: 0, .usage: "print copyright and version info" },
95 { .arg: "-h", .kind: argFlag, .val: &printHelp, .size: 0, .usage: "print usage information" },
96 { .arg: "-help", .kind: argFlag, .val: &printHelp, .size: 0, .usage: "print usage information" },
97 { .arg: "--help", .kind: argFlag, .val: &printHelp, .size: 0, .usage: "print usage information" },
98 { .arg: "-?", .kind: argFlag, .val: &printHelp, .size: 0, .usage: "print usage information" },
99 {} };
100
101int main(int argc, char *argv[])
102{
103 char *imgRoot = nullptr;
104 std::optional<GooString> ownerPW, userPW;
105
106 Win32Console win32Console(&argc, &argv);
107
108 // parse args
109 const bool ok = parseArgs(args: argDesc, argc: &argc, argv);
110 if (!ok || (listImages && argc != 2) || (!listImages && argc != 3) || printVersion || printHelp) {
111 fprintf(stderr, format: "pdfimages version %s\n", PACKAGE_VERSION);
112 fprintf(stderr, format: "%s\n", popplerCopyright);
113 fprintf(stderr, format: "%s\n", xpdfCopyright);
114 if (!printVersion) {
115 printUsage(program: "pdfimages", otherArgs: "<PDF-file> <image-root>", args: argDesc);
116 }
117 if (printVersion || printHelp) {
118 return 0;
119 }
120 return 99;
121 }
122 GooString *fileName = new GooString(argv[1]);
123 if (!listImages) {
124 imgRoot = argv[2];
125 }
126
127 // read config file
128 globalParams = std::make_unique<GlobalParams>();
129 if (quiet) {
130 globalParams->setErrQuiet(quiet);
131 }
132
133 // open PDF file
134 if (ownerPassword[0] != '\001') {
135 ownerPW = GooString(ownerPassword);
136 }
137 if (userPassword[0] != '\001') {
138 userPW = GooString(userPassword);
139 }
140 if (fileName->cmp(sA: "-") == 0) {
141 delete fileName;
142 fileName = new GooString("fd://0");
143 }
144
145 std::unique_ptr<PDFDoc> doc = PDFDocFactory().createPDFDoc(uri: *fileName, ownerPassword: ownerPW, userPassword: userPW);
146 delete fileName;
147
148 if (!doc->isOk()) {
149 return 1;
150 }
151
152 // check for copy permission
153#ifdef ENFORCE_PERMISSIONS
154 if (!doc->okToCopy()) {
155 error(errNotAllowed, -1, "Copying of images from this document is not allowed.");
156 return 3;
157 }
158#endif
159
160 // get page range
161 if (firstPage < 1) {
162 firstPage = 1;
163 }
164 if (firstPage > doc->getNumPages()) {
165 error(category: errCommandLine, pos: -1, msg: "Wrong page range given: the first page ({0:d}) can not be larger then the number of pages in the document ({1:d}).", firstPage, doc->getNumPages());
166 return 99;
167 }
168 if (lastPage < 1 || lastPage > doc->getNumPages()) {
169 lastPage = doc->getNumPages();
170 }
171 if (lastPage < firstPage) {
172 error(category: errCommandLine, pos: -1, msg: "Wrong page range given: the first page ({0:d}) can not be after the last page ({1:d}).", firstPage, lastPage);
173 return 99;
174 }
175
176 // write image files
177 ImageOutputDev *imgOut = new ImageOutputDev(imgRoot, pageNames, listImages);
178 if (imgOut->isOk()) {
179 if (allFormats) {
180 imgOut->enablePNG(png: true);
181 imgOut->enableTiff(tiff: true);
182 imgOut->enableJpeg(jpeg: true);
183 imgOut->enableJpeg2000(jp2: true);
184 imgOut->enableJBig2(jbig2: true);
185 imgOut->enableCCITT(ccitt: true);
186 } else {
187 imgOut->enablePNG(png: enablePNG);
188 imgOut->enableTiff(tiff: enableTiff);
189 imgOut->enableJpeg(jpeg: dumpJPEG);
190 imgOut->enableJpeg2000(jp2: dumpJP2);
191 imgOut->enableJBig2(jbig2: dumpJBIG2);
192 imgOut->enableCCITT(ccitt: dumpCCITT);
193 }
194 imgOut->enablePrintFilenames(filenames: printFilenames);
195 doc->displayPages(out: imgOut, firstPage, lastPage, hDPI: 72, vDPI: 72, rotate: 0, useMediaBox: true, crop: false, printing: false);
196 }
197 const int exitCode = imgOut->isOk() ? 0 : imgOut->getErrorCode();
198 delete imgOut;
199 return exitCode;
200}
201

source code of poppler/utils/pdfimages.cc