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,6 +728,15 @@ class QPDF | ||
| 728 | 728 | ||
| 729 | private: | 729 | private: |
| 730 | static void | 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 | getLinearizedParts( | 740 | getLinearizedParts( |
| 732 | QPDF& qpdf, | 741 | QPDF& qpdf, |
| 733 | std::map<int, int> const& object_stream_data, | 742 | std::map<int, int> const& object_stream_data, |
| @@ -1095,6 +1104,14 @@ class QPDF | @@ -1095,6 +1104,14 @@ class QPDF | ||
| 1095 | // For QPDFWriter: | 1104 | // For QPDFWriter: |
| 1096 | 1105 | ||
| 1097 | std::map<QPDFObjGen, QPDFXRefEntry> const& getXRefTableInternal(); | 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 | size_t tableSize(); | 1115 | size_t tableSize(); |
| 1099 | 1116 | ||
| 1100 | // Get lists of all objects in order according to the part of a linearized file that they belong | 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,6 +1430,7 @@ class QPDF | ||
| 1413 | QPDFObjGen::set& visited, | 1430 | QPDFObjGen::set& visited, |
| 1414 | bool top); | 1431 | bool top); |
| 1415 | void filterCompressedObjects(std::map<int, int> const& object_stream_data); | 1432 | void filterCompressedObjects(std::map<int, int> const& object_stream_data); |
| 1433 | + void filterCompressedObjects(QPDFWriter::ObjTable const& object_stream_data); | ||
| 1416 | 1434 | ||
| 1417 | // JSON import | 1435 | // JSON import |
| 1418 | void importJSON(std::shared_ptr<InputSource>, bool must_be_complete); | 1436 | void importJSON(std::shared_ptr<InputSource>, bool must_be_complete); |
libqpdf/QPDFWriter.cc
| @@ -2576,7 +2576,7 @@ QPDFWriter::writeLinearized() | @@ -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 | std::vector<QPDFObjectHandle> part4; | 2581 | std::vector<QPDFObjectHandle> part4; |
| 2582 | std::vector<QPDFObjectHandle> part6; | 2582 | std::vector<QPDFObjectHandle> part6; |
libqpdf/QPDF_optimization.cc
| @@ -5,6 +5,7 @@ | @@ -5,6 +5,7 @@ | ||
| 5 | #include <qpdf/QPDF.hh> | 5 | #include <qpdf/QPDF.hh> |
| 6 | 6 | ||
| 7 | #include <qpdf/QPDFExc.hh> | 7 | #include <qpdf/QPDFExc.hh> |
| 8 | +#include <qpdf/QPDFWriter_private.hh> | ||
| 8 | #include <qpdf/QPDF_Array.hh> | 9 | #include <qpdf/QPDF_Array.hh> |
| 9 | #include <qpdf/QPDF_Dictionary.hh> | 10 | #include <qpdf/QPDF_Dictionary.hh> |
| 10 | #include <qpdf/QTC.hh> | 11 | #include <qpdf/QTC.hh> |
| @@ -59,6 +60,23 @@ QPDF::optimize( | @@ -59,6 +60,23 @@ QPDF::optimize( | ||
| 59 | bool allow_changes, | 60 | bool allow_changes, |
| 60 | std::function<int(QPDFObjectHandle&)> skip_stream_parameters) | 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 | if (!m->obj_user_to_objects.empty()) { | 80 | if (!m->obj_user_to_objects.empty()) { |
| 63 | // already optimized | 81 | // already optimized |
| 64 | return; | 82 | return; |
| @@ -379,3 +397,45 @@ QPDF::filterCompressedObjects(std::map<int, int> const& object_stream_data) | @@ -379,3 +397,45 @@ QPDF::filterCompressedObjects(std::map<int, int> const& object_stream_data) | ||
| 379 | m->obj_user_to_objects = t_obj_user_to_objects; | 397 | m->obj_user_to_objects = t_obj_user_to_objects; |
| 380 | m->object_to_obj_users = t_object_to_obj_users; | 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 | +} |