aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorJustin Gassner <justin.gassner@mailbox.org>2023-03-05 19:23:26 +0100
committerJustin Gassner <justin.gassner@mailbox.org>2024-02-29 13:35:29 +0100
commit296033668c8003421b1c5d10cf58a9a7f0ed57e4 (patch)
treec66875193864f2b96cc07b2efd4535ca2b82ff2d
parent3b97c9bd266b7c32ea36d3536e22dab77412886d (diff)
downloadqpdf-zopfli.tar.zst
Support and force zopfli compressionzopfli
Original patch developed by jarnoh [1] and ported by me. [1] https://github.com/jarnoh/qpdf
-rw-r--r--.gitmodules3
-rw-r--r--include/qpdf/Pl_Flate.hh3
-rw-r--r--libqpdf/Pl_Flate.cc62
m---------zopfli0
4 files changed, 67 insertions, 1 deletions
diff --git a/.gitmodules b/.gitmodules
new file mode 100644
index 00000000..827f1bd3
--- /dev/null
+++ b/.gitmodules
@@ -0,0 +1,3 @@
+[submodule "zopfli"]
+ path = zopfli
+ url = https://github.com/google/zopfli
diff --git a/include/qpdf/Pl_Flate.hh b/include/qpdf/Pl_Flate.hh
index 41ae7e4a..325c84b6 100644
--- a/include/qpdf/Pl_Flate.hh
+++ b/include/qpdf/Pl_Flate.hh
@@ -90,6 +90,9 @@ class QPDF_DLL_CLASS Pl_Flate: public Pipeline
std::function<void(char const*, int)> callback;
};
+ unsigned char* inbuf; /* additional buffer for zopfli input */
+ size_t inbuf_size;
+
std::shared_ptr<Members> m;
};
diff --git a/libqpdf/Pl_Flate.cc b/libqpdf/Pl_Flate.cc
index d332e635..7fe8cc01 100644
--- a/libqpdf/Pl_Flate.cc
+++ b/libqpdf/Pl_Flate.cc
@@ -7,6 +7,29 @@
#include <qpdf/QIntC.hh>
#include <qpdf/QUtil.hh>
+#define USE_ZOPFLI 1
+
+#if USE_ZOPFLI
+// quick hack, link zopfli here
+extern "C" {
+#define adler32 zopfli_adler32
+#include "../zopfli/src/zopfli/zopfli.h"
+#include "../zopfli/src/zopfli/blocksplitter.c"
+#include "../zopfli/src/zopfli/cache.c"
+#include "../zopfli/src/zopfli/deflate.c"
+#include "../zopfli/src/zopfli/hash.c"
+#include "../zopfli/src/zopfli/gzip_container.c"
+#include "../zopfli/src/zopfli/katajainen.c"
+#include "../zopfli/src/zopfli/lz77.c"
+#include "../zopfli/src/zopfli/squeeze.c"
+#include "../zopfli/src/zopfli/tree.c"
+#include "../zopfli/src/zopfli/util.c"
+#include "../zopfli/src/zopfli/zlib_container.c"
+#include "../zopfli/src/zopfli/zopfli_lib.c"
+#undef adler32
+}
+#endif
+
int Pl_Flate::compression_level = Z_DEFAULT_COMPRESSION;
Pl_Flate::Members::Members(size_t out_bufsize, action_e action) :
@@ -54,13 +77,18 @@ Pl_Flate::Members::~Members()
Pl_Flate::Pl_Flate(
char const* identifier, Pipeline* next, action_e action, unsigned int out_bufsize_int) :
Pipeline(identifier, next),
- m(new Members(QIntC::to_size(out_bufsize_int), action))
+ m(new Members(QIntC::to_size(out_bufsize_int), action)),
+ inbuf(0), inbuf_size(0)
{
}
Pl_Flate::~Pl_Flate() // NOLINT (modernize-use-equals-default)
{
// Must be explicit and not inline -- see QPDF_DLL_CLASS in README-maintainer
+
+#if USE_ZOPFLI
+ free(inbuf); inbuf = 0;
+#endif
}
void
@@ -109,6 +137,17 @@ Pl_Flate::handleData(unsigned char const* data, size_t len, int flush)
zstream.next_in = const_cast<unsigned char*>(data);
zstream.avail_in = QIntC::to_uint(len);
+#if USE_ZOPFLI
+ if (this->m->action == a_deflate)
+ {
+ inbuf = static_cast<unsigned char*>(realloc(inbuf, inbuf_size+len));
+ if(!inbuf) throw std::runtime_error("realloc failed");
+ memcpy(inbuf+inbuf_size, data, len);
+ inbuf_size += len;
+ return;
+ }
+#endif
+
if (!m->initialized) {
int err = Z_OK;
@@ -188,6 +227,27 @@ void
Pl_Flate::finish()
{
try {
+#if USE_ZOPFLI
+ if (m->action == a_deflate)
+ {
+ ZopfliOptions options;
+ ZopfliInitOptions(&options);
+
+ unsigned char* out = 0;
+ size_t out_size = 0;
+
+ ZopfliCompress(&options, ZOPFLI_FORMAT_ZLIB, inbuf, inbuf_size, &out, &out_size);
+ free(inbuf); inbuf = 0;
+
+ if(inbuf_size!=0 && out_size==0) throw std::runtime_error("zopfli failed");
+
+ getNext()->write(out, out_size);
+ getNext()->finish();
+ free(out); out = 0;
+
+ return;
+ }
+#endif
if (m->outbuf.get()) {
if (m->initialized) {
z_stream& zstream = *(static_cast<z_stream*>(m->zdata));
diff --git a/zopfli b/zopfli
new file mode 160000
+Subproject 831773bc28e318b91a3255fa12c9fcde1606058