summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorRobin Watts <robin.watts@artifex.com>2017-10-09 17:36:36 +0100
committerRobin Watts <robin.watts@artifex.com>2017-10-13 15:57:25 +0100
commit680594660b6b680326cd56fe5ea604a0b55efcfa (patch)
tree5dc41ad31fd8d61f0633728c870750c9cbd11389
parent167da6144dc8bcafc1f1476d73b3b6d18541a8a8 (diff)
downloadmupdf-680594660b6b680326cd56fe5ea604a0b55efcfa.tar.xz
Add fz_deflate family of functions.
This gives us a friendlier interface to zlib. Simplifies PNG output and PCLM output code.
-rw-r--r--include/mupdf/fitz.h1
-rw-r--r--include/mupdf/fitz/compress.h50
-rw-r--r--platform/win32/libmupdf.vcproj8
-rw-r--r--source/fitz/compress.c97
-rw-r--r--source/fitz/output-pclm.c6
-rw-r--r--source/fitz/output-png.c24
6 files changed, 162 insertions, 24 deletions
diff --git a/include/mupdf/fitz.h b/include/mupdf/fitz.h
index 9b6d6aa9..9f697c8a 100644
--- a/include/mupdf/fitz.h
+++ b/include/mupdf/fitz.h
@@ -23,6 +23,7 @@ extern "C" {
/* I/O */
#include "mupdf/fitz/buffer.h"
#include "mupdf/fitz/stream.h"
+#include "mupdf/fitz/compress.h"
#include "mupdf/fitz/compressed-buffer.h"
#include "mupdf/fitz/filter.h"
#include "mupdf/fitz/output.h"
diff --git a/include/mupdf/fitz/compress.h b/include/mupdf/fitz/compress.h
new file mode 100644
index 00000000..cfd4ed1a
--- /dev/null
+++ b/include/mupdf/fitz/compress.h
@@ -0,0 +1,50 @@
+#ifndef MUPDF_FITZ_COMPRESS_H
+#define MUPDF_FITZ_COMPRESS_H
+
+#include "mupdf/fitz/system.h"
+
+typedef enum
+{
+ FZ_DEFLATE_NONE = 0,
+ FZ_DEFLATE_BEST_SPEED = 1,
+ FZ_DEFLATE_BEST = 9,
+ FZ_DEFLATE_DEFAULT = -1
+} fz_deflate_level;
+
+/*
+ fz_deflate_bound: Returns the upper bound on the
+ size of flated data of length size.
+ */
+size_t fz_deflate_bound(fz_context *ctx, size_t size);
+
+/*
+ fz_deflate: Compress source_length bytes of data starting
+ at source, into a buffer of length *destLen, starting at dest.
+ *compressed_length will be updated on exit to contain the size
+ actually used.
+ */
+void fz_deflate(fz_context *ctx, unsigned char *dest, size_t *compressed_length, const unsigned char *source, size_t source_length, fz_deflate_level level);
+
+/*
+ fz_new_deflated_data: Compress source_length bytes of data starting
+ at source, into a new memory block malloced for that purpose.
+ *compressed_length is updated on exit to contain the size used.
+ Ownership of the block is returned from this function, and the
+ caller is therefore responsible for freeing it. The block may be
+ considerably larger than is actually required. The caller is
+ free to fz_realloc it down if it wants to.
+*/
+unsigned char *fz_new_deflated_data(fz_context *ctx, size_t *compressed_length, const unsigned char *source, size_t source_length, fz_deflate_level level);
+
+/*
+ fz_new_deflated_data_from_buffer: Compress the contents of a fz_buffer into a
+ new block malloced for that purpose. *compressed_length is updated
+ on exit to contain the size used. Ownership of the block is
+ returned from this function, and the caller is therefore responsible
+ for freeing it. The block may be considerably larger than is
+ actually required. The caller is free to fz_realloc it down if it
+ wants to.
+*/
+unsigned char *fz_new_deflated_data_from_buffer(fz_context *ctx, size_t *compressed_length, fz_buffer *buffer, fz_deflate_level level);
+
+#endif
diff --git a/platform/win32/libmupdf.vcproj b/platform/win32/libmupdf.vcproj
index 02bed939..024591db 100644
--- a/platform/win32/libmupdf.vcproj
+++ b/platform/win32/libmupdf.vcproj
@@ -1545,6 +1545,10 @@
>
</File>
<File
+ RelativePath="..\..\source\fitz\compress.c"
+ >
+ </File>
+ <File
RelativePath="..\..\source\fitz\compressed-buffer.c"
>
</File>
@@ -2316,6 +2320,10 @@
>
</File>
<File
+ RelativePath="..\..\include\mupdf\fitz\compress.h"
+ >
+ </File>
+ <File
RelativePath="..\..\include\mupdf\fitz\compressed-buffer.h"
>
</File>
diff --git a/source/fitz/compress.c b/source/fitz/compress.c
new file mode 100644
index 00000000..439c461e
--- /dev/null
+++ b/source/fitz/compress.c
@@ -0,0 +1,97 @@
+#include "mupdf/fitz.h"
+
+#include <zlib.h>
+
+static void *fz_z_alloc(void *opaque, unsigned int count, unsigned int size)
+{
+ fz_context *ctx = (fz_context *)opaque;
+ size_t c = count * size;
+
+ return fz_malloc_no_throw(ctx, c);
+}
+
+static void fz_z_free(void *opaque, void *addr)
+{
+ fz_context *ctx = (fz_context *)opaque;
+
+ fz_free(ctx, addr);
+}
+
+void fz_deflate(fz_context *ctx, unsigned char *dest, size_t *destLen, const unsigned char *source, size_t sourceLen, fz_deflate_level level)
+{
+ z_stream stream;
+ int err;
+ size_t left;
+
+ left = *destLen;
+ *destLen = 0;
+
+ stream.zalloc = fz_z_alloc;
+ stream.zfree = fz_z_free;
+ stream.opaque = ctx;
+
+ err = deflateInit(&stream, (int)level);
+ if (err != Z_OK)
+ fz_throw(ctx, FZ_ERROR_GENERIC, "zlib compression failed: %d", err);
+
+ stream.next_out = dest;
+ stream.avail_out = 0;
+ stream.next_in = (z_const Bytef *)source;
+ stream.avail_in = 0;
+
+ do {
+ if (stream.avail_out == 0) {
+ stream.avail_out = left > UINT_MAX ? UINT_MAX : (uInt)left;
+ left -= stream.avail_out;
+ }
+ if (stream.avail_in == 0) {
+ stream.avail_in = sourceLen > UINT_MAX ? UINT_MAX : (uInt)sourceLen;
+ sourceLen -= stream.avail_in;
+ }
+ err = deflate(&stream, sourceLen ? Z_NO_FLUSH : Z_FINISH);
+ } while (err == Z_OK);
+
+ /* We might have problems if the compressed length > uLong sized. Tough, for now. */
+ *destLen = stream.total_out;
+ deflateEnd(&stream);
+ if (err != Z_STREAM_END)
+ fz_throw(ctx, FZ_ERROR_GENERIC, "Zlib failure: %d", err);
+}
+
+unsigned char *fz_new_deflated_data(fz_context *ctx, size_t *compressed_length, const unsigned char *source, size_t source_length, fz_deflate_level level)
+{
+ size_t bound = fz_deflate_bound(ctx, source_length);
+ unsigned char *cdata = fz_malloc(ctx, bound);
+ *compressed_length = 0;
+
+ fz_try(ctx)
+ fz_deflate(ctx, cdata, &bound, source, source_length, level);
+ fz_catch(ctx)
+ {
+ fz_free(ctx, cdata);
+ fz_rethrow(ctx);
+ }
+
+ *compressed_length = bound;
+ return cdata;
+}
+
+unsigned char *fz_new_deflated_data_from_buffer(fz_context *ctx, size_t *compressed_length, fz_buffer *buffer, fz_deflate_level level)
+{
+ unsigned char *data;
+ size_t size = fz_buffer_storage(ctx, buffer, &data);
+
+ if (size == 0 || data == NULL)
+ {
+ *compressed_length = 0;
+ return NULL;
+ }
+
+ return fz_new_deflated_data(ctx, compressed_length, data, size, level);
+}
+
+size_t fz_deflate_bound(fz_context *ctx, size_t size)
+{
+ /* Copied from zlib to account for size_t vs uLong */
+ return size + (size >> 12) + (size >> 14) + (size >> 25) + 13;
+}
diff --git a/source/fitz/output-pclm.c b/source/fitz/output-pclm.c
index 52f673a1..0d1f728c 100644
--- a/source/fitz/output-pclm.c
+++ b/source/fitz/output-pclm.c
@@ -122,7 +122,7 @@ pclm_write_header(fz_context *ctx, fz_band_writer *writer_, const fz_colorspace
fz_free(ctx, writer->stripbuf);
fz_free(ctx, writer->compbuf);
writer->stripbuf = fz_malloc(ctx, w * sh * n);
- writer->complen = compressBound(w * sh * n);
+ writer->complen = fz_deflate_bound(ctx, w * sh * n);
writer->compbuf = fz_malloc(ctx, writer->complen);
/* Send the file header on the first page */
@@ -193,9 +193,7 @@ flush_strip(fz_context *ctx, pclm_band_writer *writer, int fill)
if (writer->options.compress)
{
uLongf destLen = writer->complen;
- int err = compress(writer->compbuf, &destLen, data, (uLongf)len);
- if (err != Z_OK)
- fz_throw(ctx, FZ_ERROR_GENERIC, "cannot compress strip: %d", err);
+ fz_deflate(ctx, writer->compbuf, &destLen, data, len, FZ_DEFLATE_DEFAULT);
len = destLen;
data = writer->compbuf;
}
diff --git a/source/fitz/output-png.c b/source/fitz/output-png.c
index 38bfa778..d21bc59b 100644
--- a/source/fitz/output-png.c
+++ b/source/fitz/output-png.c
@@ -86,34 +86,18 @@ static void
png_write_icc(fz_context *ctx, png_band_writer *writer, const fz_colorspace *cs)
{
fz_output *out = writer->super.out;
- int size;
+ size_t size, csize;
fz_buffer *buffer = fz_icc_data_from_icc_colorspace(ctx, cs);
- unsigned char *data;
unsigned char *pos, *cdata, *chunk = NULL;
- uLong bound;
- uLongf csize;
- uLong long_size;
- int t;
- long_size = (uLong)fz_buffer_storage(ctx, buffer, &data);
+ /* Deflate the profile */
+ cdata = fz_new_deflated_data_from_buffer(ctx, &csize, buffer, FZ_DEFLATE_DEFAULT);
- if (!data)
+ if (!cdata)
return;
- /* Deflate the profile */
- bound = compressBound(long_size);
- cdata = fz_malloc(ctx, bound);
- csize = (uLongf)bound;
- t = compress(cdata, &csize, data, long_size);
- if (t != Z_OK)
- {
- fz_free(ctx, cdata);
- fz_throw(ctx, FZ_ERROR_GENERIC, "cannot deflate icc buffer");
- }
size = csize + strlen("MuPDF Profile") + 2;
- fz_var(cdata);
-
fz_try(ctx)
{
chunk = fz_calloc(ctx, size, 1);