2
1
mirror of https://github.com/qpdf/qpdf.git synced 2024-06-04 03:10:52 +00:00

Keep file open while adding its pages during merge (fixes #217)

This commit is contained in:
Jay Berkenbilt 2018-08-04 19:58:13 -04:00
parent 4f4c627b77
commit fe769f2723
2 changed files with 32 additions and 3 deletions

View File

@ -1,5 +1,8 @@
2018-08-04 Jay Berkenbilt <ejb@ql.org> 2018-08-04 Jay Berkenbilt <ejb@ql.org>
* Performance fix: optimize page merging operation to avoid
unnecessary open/close calls on files being merged. Fixes #217.
* Add ClosedFileInputSource::stayOpen method, enabling a * Add ClosedFileInputSource::stayOpen method, enabling a
ClosedFileInputSource to stay open during manually indicated ClosedFileInputSource to stay open during manually indicated
periods of high activity, thus reducing the overhead of frequent periods of high activity, thus reducing the overhead of frequent

View File

@ -2103,6 +2103,7 @@ static void handle_page_specs(QPDF& pdf, Options& o,
// Create a QPDF object for each file that we may take pages from. // Create a QPDF object for each file that we may take pages from.
std::map<std::string, QPDF*> page_spec_qpdfs; std::map<std::string, QPDF*> page_spec_qpdfs;
std::map<std::string, ClosedFileInputSource*> page_spec_cfis;
page_spec_qpdfs[o.infilename] = &pdf; page_spec_qpdfs[o.infilename] = &pdf;
std::vector<QPDFPageData> parsed_specs; std::vector<QPDFPageData> parsed_specs;
for (std::vector<PageSpec>::iterator iter = o.page_specs.begin(); for (std::vector<PageSpec>::iterator iter = o.page_specs.begin();
@ -2136,10 +2137,14 @@ static void handle_page_specs(QPDF& pdf, Options& o,
std::cout << whoami << ": processing " std::cout << whoami << ": processing "
<< page_spec.filename << std::endl; << page_spec.filename << std::endl;
} }
qpdf->processInputSource( ClosedFileInputSource* cis =
new ClosedFileInputSource( new ClosedFileInputSource(page_spec.filename.c_str());
page_spec.filename.c_str()), password); PointerHolder<InputSource> is(cis);
cis->stayOpen(true);
qpdf->processInputSource(is, password);
cis->stayOpen(false);
page_spec_qpdfs[page_spec.filename] = qpdf; page_spec_qpdfs[page_spec.filename] = qpdf;
page_spec_cfis[page_spec.filename] = cis;
} }
// Read original pages from the PDF, and parse the page range // Read original pages from the PDF, and parse the page range
@ -2156,9 +2161,20 @@ static void handle_page_specs(QPDF& pdf, Options& o,
page_spec_qpdfs.begin(); page_spec_qpdfs.begin();
iter != page_spec_qpdfs.end(); ++iter) iter != page_spec_qpdfs.end(); ++iter)
{ {
std::string const& filename = (*iter).first;
ClosedFileInputSource* cis = 0;
if (page_spec_cfis.count(filename))
{
cis = page_spec_cfis[filename];
cis->stayOpen(true);
}
QPDFPageDocumentHelper dh(*((*iter).second)); QPDFPageDocumentHelper dh(*((*iter).second));
dh.pushInheritedAttributesToPage(); dh.pushInheritedAttributesToPage();
dh.removeUnreferencedResources(); dh.removeUnreferencedResources();
if (cis)
{
cis->stayOpen(false);
}
} }
} }
@ -2204,7 +2220,17 @@ static void handle_page_specs(QPDF& pdf, Options& o,
// Pages are specified from 1 but numbered from 0 in the // Pages are specified from 1 but numbered from 0 in the
// vector // vector
int pageno = *pageno_iter - 1; int pageno = *pageno_iter - 1;
ClosedFileInputSource* cis = 0;
if (page_spec_cfis.count(page_data.filename))
{
cis = page_spec_cfis[page_data.filename];
cis->stayOpen(true);
}
dh.addPage(page_data.orig_pages.at(pageno), false); dh.addPage(page_data.orig_pages.at(pageno), false);
if (cis)
{
cis->stayOpen(false);
}
if (page_data.qpdf == &pdf) if (page_data.qpdf == &pdf)
{ {
// This is a page from the original file. Keep track // This is a page from the original file. Keep track