Commit fe36ef141c7d77548175666eb952cd185f2d9fa6

Authored by Jay Berkenbilt
Committed by GitHub
2 parents 1e53da74 f6b13fcc

Merge pull request #924 from cdosborn/main

Improve --optimize-images to find images nested within XObjects
libqpdf/QPDFJob.cc
... ... @@ -2363,31 +2363,30 @@ QPDFJob::handleTransformations(QPDF& pdf)
2363 2363 int pageno = 0;
2364 2364 for (auto& ph: dh.getAllPages()) {
2365 2365 ++pageno;
2366   - QPDFObjectHandle page = ph.getObjectHandle();
2367   - for (auto& iter2: ph.getImages()) {
2368   - std::string name = iter2.first;
2369   - QPDFObjectHandle& image = iter2.second;
2370   - ImageOptimizer* io = new ImageOptimizer(
2371   - *this,
2372   - m->oi_min_width,
2373   - m->oi_min_height,
2374   - m->oi_min_area,
2375   - image);
2376   - std::shared_ptr<QPDFObjectHandle::StreamDataProvider> sdp(io);
2377   - if (io->evaluate(
2378   - "image " + name + " on page " +
2379   - std::to_string(pageno))) {
2380   - QPDFObjectHandle new_image = pdf.newStream();
2381   - new_image.replaceDict(image.getDict().shallowCopy());
2382   - new_image.replaceStreamData(
2383   - sdp,
2384   - QPDFObjectHandle::newName("/DCTDecode"),
2385   - QPDFObjectHandle::newNull());
2386   - ph.getAttribute("/Resources", true)
2387   - .getKey("/XObject")
2388   - .replaceKey(name, new_image);
2389   - }
2390   - }
  2366 + ph.forEachImage(
  2367 + true,
  2368 + [this, pageno, &pdf](
  2369 + QPDFObjectHandle& obj,
  2370 + QPDFObjectHandle& xobj_dict,
  2371 + std::string const& key) {
  2372 + auto io = std::make_unique<ImageOptimizer>(
  2373 + *this,
  2374 + m->oi_min_width,
  2375 + m->oi_min_height,
  2376 + m->oi_min_area,
  2377 + obj);
  2378 + if (io->evaluate(
  2379 + "image " + key + " on page " +
  2380 + std::to_string(pageno))) {
  2381 + QPDFObjectHandle new_image = pdf.newStream();
  2382 + new_image.replaceDict(obj.getDict().shallowCopy());
  2383 + new_image.replaceStreamData(
  2384 + std::move(io),
  2385 + QPDFObjectHandle::newName("/DCTDecode"),
  2386 + QPDFObjectHandle::newNull());
  2387 + xobj_dict.replaceKey(key, new_image);
  2388 + }
  2389 + });
2391 2390 }
2392 2391 }
2393 2392 if (m->generate_appearances) {
... ...
qpdf/qtest/image-optimization.test
... ... @@ -33,6 +33,8 @@ my @image_opt = (
33 33 ['large-inline-image', 'inline-images-keep-all', '--keep-inline-images'],
34 34 ['unsupported-optimization', 'unsupported',
35 35 '--oi-min-width=0 --oi-min-height=0 --oi-min-area=0'],
  36 + ['nested-images', 'nested-images',
  37 + '--oi-min-width=0 --oi-min-height=0 --oi-min-area=0']
36 38 );
37 39  
38 40 my $n_tests = 2 * scalar(@image_opt);
... ...
qpdf/qtest/qpdf/nested-images.pdf 0 โ†’ 100644
No preview for this file type
qpdf/qtest/qpdf/optimize-images-nested-images-json.out 0 โ†’ 100644
  1 +{
  2 + "version": 2,
  3 + "parameters": {
  4 + "decodelevel": "generalized"
  5 + },
  6 + "pages": [
  7 + {
  8 + "contents": [
  9 + "4 0 R"
  10 + ],
  11 + "images": [],
  12 + "label": null,
  13 + "object": "3 0 R",
  14 + "outlines": [],
  15 + "pageposfrom1": 1
  16 + }
  17 + ]
  18 +}
... ...
qpdf/qtest/qpdf/optimize-images-nested-images.out 0 โ†’ 100644
  1 +qpdf: image /X1 on page 1: optimizing image reduces size from 2628 to ...
  2 +qpdf: wrote file a.pdf
... ...