From e62f1e4e4457487b3ae7b729b5fb7a78081b0478 Mon Sep 17 00:00:00 2001 From: Jay Berkenbilt Date: Sat, 5 Apr 2025 20:52:17 -0400 Subject: [PATCH] Add Pl_DCT::make_compress_config --- include/qpdf/Pl_DCT.hh | 5 +++++ libqpdf/Pl_DCT.cc | 24 +++++++++++++++++++++++- libqpdf/QPDFJob.cc | 4 +++- libtests/dct_compress.cc | 7 ++++++- manual/release-notes.rst | 6 ++++++ 5 files changed, 43 insertions(+), 3 deletions(-) diff --git a/include/qpdf/Pl_DCT.hh b/include/qpdf/Pl_DCT.hh index 02f4a34..09a7277 100644 --- a/include/qpdf/Pl_DCT.hh +++ b/include/qpdf/Pl_DCT.hh @@ -24,6 +24,7 @@ #include #include +#include // jpeglib.h must be included after cstddef or else it messes up the definition of size_t. #include @@ -62,6 +63,10 @@ class QPDF_DLL_CLASS Pl_DCT: public Pipeline virtual void apply(jpeg_compress_struct*) = 0; }; + QPDF_DLL + static std::shared_ptr + make_compress_config(std::function); + // Constructor for compressing image data QPDF_DLL Pl_DCT( diff --git a/libqpdf/Pl_DCT.cc b/libqpdf/Pl_DCT.cc index 92af9c9..2e480ec 100644 --- a/libqpdf/Pl_DCT.cc +++ b/libqpdf/Pl_DCT.cc @@ -1,6 +1,5 @@ #include -#include "qpdf/QPDFLogger.hh" #include #include @@ -14,6 +13,23 @@ namespace { + class FunctionCallbackConfig: public Pl_DCT::CompressConfig + { + public: + explicit FunctionCallbackConfig(std::function f) : + f(std::move(f)) + { + } + ~FunctionCallbackConfig() override = default; + void + apply(jpeg_compress_struct* config) override + { + f(config); + }; + + std::function f; + }; + struct qpdf_jpeg_error_mgr { struct jpeg_error_mgr pub; @@ -407,3 +423,9 @@ Pl_DCT::decompress(void* cinfo_p, Buffer* b) (void)jpeg_finish_decompress(cinfo); next()->finish(); } + +std::shared_ptr +Pl_DCT::make_compress_config(std::function f) +{ + return std::make_shared(f); +} diff --git a/libqpdf/QPDFJob.cc b/libqpdf/QPDFJob.cc index efa07d3..3077200 100644 --- a/libqpdf/QPDFJob.cc +++ b/libqpdf/QPDFJob.cc @@ -57,6 +57,7 @@ namespace size_t oi_min_height; size_t oi_min_area; QPDFObjectHandle image; + std::shared_ptr config; }; class DiscardContents: public QPDFObjectHandle::ParserCallbacks @@ -115,6 +116,7 @@ ImageOptimizer::ImageOptimizer( oi_min_area(oi_min_area), image(image) { + config = Pl_DCT::make_compress_config([](jpeg_compress_struct* config) {}); } std::shared_ptr @@ -195,7 +197,7 @@ ImageOptimizer::makePipeline(std::string const& description, Pipeline* next) return result; } - result = std::make_shared("jpg", next, w, h, components, cs); + result = std::make_shared("jpg", next, w, h, components, cs, config.get()); return result; } diff --git a/libtests/dct_compress.cc b/libtests/dct_compress.cc index 0042894..c5f8396 100644 --- a/libtests/dct_compress.cc +++ b/libtests/dct_compress.cc @@ -1,6 +1,7 @@ #include #include #include +#include #include #include @@ -50,12 +51,16 @@ main(int argc, char* argv[]) FILE* infile = QUtil::safe_fopen(infilename, "rb"); FILE* outfile = QUtil::safe_fopen(outfilename, "wb"); Pl_StdioFile out("stdout", outfile); + bool called = false; + auto callback = [&called](jpeg_compress_struct*) { called = true; }; + auto config = Pl_DCT::make_compress_config(callback); unsigned char buf[100]; - Pl_DCT dct("dct", &out, width, height, components, cs); + Pl_DCT dct("dct", &out, width, height, components, cs, config.get()); while (size_t len = fread(buf, 1, sizeof(buf), infile)) { dct.write(buf, len); } dct.finish(); + assert(called); fclose(infile); fclose(outfile); diff --git a/manual/release-notes.rst b/manual/release-notes.rst index 168d40f..cb22412 100644 --- a/manual/release-notes.rst +++ b/manual/release-notes.rst @@ -38,6 +38,12 @@ more detail. unencrypted. qpdf has always incorrectly handled all ``/Metadata`` streams as special with cleartext metadata. + - Library Enhancements + + - Add function ``Pl_DCT::make_compress_config`` to return a + ``Pl_DCT::CompressConfig`` shared pointer from a + ``std::function`` for a more modern configuration option. + - CLI Enhancements - New :qpdf:ref:`--remove-structure` option to exclude the document -- libgit2 0.21.4