Commit 97d78c75ff04e3db7801b6e609ee4f9d2e70c3fd
1 parent
0df0d00c
In QPDFWriter::writeLinearized use object table obj in call to optimize
Showing
3 changed files
with
79 additions
and
1 deletions
include/qpdf/QPDF.hh
| ... | ... | @@ -728,6 +728,15 @@ class QPDF |
| 728 | 728 | |
| 729 | 729 | private: |
| 730 | 730 | static void |
| 731 | + optimize( | |
| 732 | + QPDF& qpdf, | |
| 733 | + QPDFWriter::ObjTable const& obj, | |
| 734 | + std::function<int(QPDFObjectHandle&)> skip_stream_parameters) | |
| 735 | + { | |
| 736 | + return qpdf.optimize(obj, skip_stream_parameters); | |
| 737 | + } | |
| 738 | + | |
| 739 | + static void | |
| 731 | 740 | getLinearizedParts( |
| 732 | 741 | QPDF& qpdf, |
| 733 | 742 | std::map<int, int> const& object_stream_data, |
| ... | ... | @@ -1095,6 +1104,14 @@ class QPDF |
| 1095 | 1104 | // For QPDFWriter: |
| 1096 | 1105 | |
| 1097 | 1106 | std::map<QPDFObjGen, QPDFXRefEntry> const& getXRefTableInternal(); |
| 1107 | + template <typename T> | |
| 1108 | + void optimize_internal( | |
| 1109 | + T const& object_stream_data, | |
| 1110 | + bool allow_changes = true, | |
| 1111 | + std::function<int(QPDFObjectHandle&)> skip_stream_parameters = nullptr); | |
| 1112 | + void optimize( | |
| 1113 | + QPDFWriter::ObjTable const& obj, | |
| 1114 | + std::function<int(QPDFObjectHandle&)> skip_stream_parameters); | |
| 1098 | 1115 | size_t tableSize(); |
| 1099 | 1116 | |
| 1100 | 1117 | // Get lists of all objects in order according to the part of a linearized file that they belong |
| ... | ... | @@ -1413,6 +1430,7 @@ class QPDF |
| 1413 | 1430 | QPDFObjGen::set& visited, |
| 1414 | 1431 | bool top); |
| 1415 | 1432 | void filterCompressedObjects(std::map<int, int> const& object_stream_data); |
| 1433 | + void filterCompressedObjects(QPDFWriter::ObjTable const& object_stream_data); | |
| 1416 | 1434 | |
| 1417 | 1435 | // JSON import |
| 1418 | 1436 | void importJSON(std::shared_ptr<InputSource>, bool must_be_complete); | ... | ... |
libqpdf/QPDFWriter.cc
| ... | ... | @@ -2576,7 +2576,7 @@ QPDFWriter::writeLinearized() |
| 2576 | 2576 | } |
| 2577 | 2577 | }; |
| 2578 | 2578 | |
| 2579 | - m->pdf.optimize(m->object_to_object_stream_no_gen, true, skip_stream_parameters); | |
| 2579 | + QPDF::Writer::optimize(m->pdf, m->obj, skip_stream_parameters); | |
| 2580 | 2580 | |
| 2581 | 2581 | std::vector<QPDFObjectHandle> part4; |
| 2582 | 2582 | std::vector<QPDFObjectHandle> part6; | ... | ... |
libqpdf/QPDF_optimization.cc
| ... | ... | @@ -5,6 +5,7 @@ |
| 5 | 5 | #include <qpdf/QPDF.hh> |
| 6 | 6 | |
| 7 | 7 | #include <qpdf/QPDFExc.hh> |
| 8 | +#include <qpdf/QPDFWriter_private.hh> | |
| 8 | 9 | #include <qpdf/QPDF_Array.hh> |
| 9 | 10 | #include <qpdf/QPDF_Dictionary.hh> |
| 10 | 11 | #include <qpdf/QTC.hh> |
| ... | ... | @@ -59,6 +60,23 @@ QPDF::optimize( |
| 59 | 60 | bool allow_changes, |
| 60 | 61 | std::function<int(QPDFObjectHandle&)> skip_stream_parameters) |
| 61 | 62 | { |
| 63 | + optimize_internal(object_stream_data, allow_changes, skip_stream_parameters); | |
| 64 | +} | |
| 65 | + | |
| 66 | +void | |
| 67 | +QPDF::optimize( | |
| 68 | + QPDFWriter::ObjTable const& obj, std::function<int(QPDFObjectHandle&)> skip_stream_parameters) | |
| 69 | +{ | |
| 70 | + optimize_internal(obj, true, skip_stream_parameters); | |
| 71 | +} | |
| 72 | + | |
| 73 | +template <typename T> | |
| 74 | +void | |
| 75 | +QPDF::optimize_internal( | |
| 76 | + T const& object_stream_data, | |
| 77 | + bool allow_changes, | |
| 78 | + std::function<int(QPDFObjectHandle&)> skip_stream_parameters) | |
| 79 | +{ | |
| 62 | 80 | if (!m->obj_user_to_objects.empty()) { |
| 63 | 81 | // already optimized |
| 64 | 82 | return; |
| ... | ... | @@ -379,3 +397,45 @@ QPDF::filterCompressedObjects(std::map<int, int> const& object_stream_data) |
| 379 | 397 | m->obj_user_to_objects = t_obj_user_to_objects; |
| 380 | 398 | m->object_to_obj_users = t_object_to_obj_users; |
| 381 | 399 | } |
| 400 | + | |
| 401 | +void | |
| 402 | +QPDF::filterCompressedObjects(QPDFWriter::ObjTable const& obj) | |
| 403 | +{ | |
| 404 | + if (obj.getStreamsEmpty()) { | |
| 405 | + return; | |
| 406 | + } | |
| 407 | + | |
| 408 | + // Transform object_to_obj_users and obj_user_to_objects so that they refer only to uncompressed | |
| 409 | + // objects. If something is a user of a compressed object, then it is really a user of the | |
| 410 | + // object stream that contains it. | |
| 411 | + | |
| 412 | + std::map<ObjUser, std::set<QPDFObjGen>> t_obj_user_to_objects; | |
| 413 | + std::map<QPDFObjGen, std::set<ObjUser>> t_object_to_obj_users; | |
| 414 | + | |
| 415 | + for (auto const& i1: m->obj_user_to_objects) { | |
| 416 | + ObjUser const& ou = i1.first; | |
| 417 | + // Loop over objects. | |
| 418 | + for (auto const& og: i1.second) { | |
| 419 | + if (auto const& i2 = obj[og].object_stream; i2 <= 0) { | |
| 420 | + t_obj_user_to_objects[ou].insert(og); | |
| 421 | + } else { | |
| 422 | + t_obj_user_to_objects[ou].insert(QPDFObjGen(i2, 0)); | |
| 423 | + } | |
| 424 | + } | |
| 425 | + } | |
| 426 | + | |
| 427 | + for (auto const& i1: m->object_to_obj_users) { | |
| 428 | + QPDFObjGen const& og = i1.first; | |
| 429 | + // Loop over obj_users. | |
| 430 | + for (auto const& ou: i1.second) { | |
| 431 | + if (auto i2 = obj[og].object_stream; i2 <= 0) { | |
| 432 | + t_object_to_obj_users[og].insert(ou); | |
| 433 | + } else { | |
| 434 | + t_object_to_obj_users[QPDFObjGen(i2, 0)].insert(ou); | |
| 435 | + } | |
| 436 | + } | |
| 437 | + } | |
| 438 | + | |
| 439 | + m->obj_user_to_objects = t_obj_user_to_objects; | |
| 440 | + m->object_to_obj_users = t_object_to_obj_users; | |
| 441 | +} | ... | ... |