[cairo] [PATCH] [pdf] Use deflate stream when writing images.

Kristian Høgsberg krh at bitplanet.net
Mon Feb 11 11:49:04 PST 2008


The deflate stream has bounded (constant) memory overhead, whereas
compress_dup() allocates memory proportional to the uncompressed data.
Should ease memory pressure for emitting images.
---
[ This is a git convention; text between the double dash above and the actual
  diff isn't part of the commit message and git-am will strip it out.
  Typically used for informal comments/discussion about the patch. ]

I wanted to eliminate compress_dup() completely, but for font subsets we
need the compressed_size up front for the /Length attribute of the dict.
I was a bit puzzled by the fact that we don't use that for images, since the
PDF specification says that it's required for all streams... maybe we could
just leave it out for fonts streams as well, or alternatively, make the length
an indirect object as we do for content streams.

Kristian

 src/cairo-pdf-surface.c |   45 ++++++++++++++++++++-------------------------
 1 files changed, 20 insertions(+), 25 deletions(-)

diff --git a/src/cairo-pdf-surface.c b/src/cairo-pdf-surface.c
index e8c7ea4..f635404 100644
--- a/src/cairo-pdf-surface.c
+++ b/src/cairo-pdf-surface.c
@@ -1286,14 +1286,15 @@ _cairo_pdf_surface_emit_smask (cairo_pdf_surface_t	*surface,
 			       cairo_pdf_resource_t	*stream_ret)
 {
     cairo_status_t status = CAIRO_STATUS_SUCCESS;
-    char *alpha, *alpha_compressed;
-    unsigned long alpha_size, alpha_compressed_size;
+    char *alpha;
+    unsigned long alpha_size;
     uint32_t *pixel32;
     uint8_t *pixel8;
     int i, x, y;
     cairo_bool_t opaque;
     uint8_t a;
     int src_bit, dst_bit;
+    cairo_output_stream_t *deflate;
 
     /* This is the only image format we support, which simplifies things. */
     assert (image->format == CAIRO_FORMAT_ARGB32 ||
@@ -1368,12 +1369,6 @@ _cairo_pdf_surface_emit_smask (cairo_pdf_surface_t	*surface,
     if (opaque)
 	goto CLEANUP_ALPHA;
 
-    alpha_compressed = compress_dup (alpha, alpha_size, &alpha_compressed_size);
-    if (alpha_compressed == NULL) {
-	status = _cairo_error (CAIRO_STATUS_NO_MEMORY);
-	goto CLEANUP_ALPHA;
-    }
-
     status = _cairo_pdf_surface_open_stream (surface,
 					     NULL,
 					     FALSE,
@@ -1387,16 +1382,18 @@ _cairo_pdf_surface_emit_smask (cairo_pdf_surface_t	*surface,
 					     image->width, image->height,
 					     image->format == CAIRO_FORMAT_A1 ? 1 : 8);
     if (status)
-	goto CLEANUP_ALPHA_COMPRESSED;
+	goto CLEANUP_ALPHA;
 
     *stream_ret = surface->pdf_stream.self;
+    deflate = _cairo_deflate_stream_create (surface->output);
+    _cairo_output_stream_write (deflate, alpha, alpha_size);
+    status = _cairo_output_stream_destroy (deflate);
+    if (status)
+	goto CLEANUP_ALPHA;
 
-    _cairo_output_stream_write (surface->output, alpha_compressed, alpha_compressed_size);
     _cairo_output_stream_printf (surface->output, "\r\n");
     status = _cairo_pdf_surface_close_stream (surface);
 
- CLEANUP_ALPHA_COMPRESSED:
-    free (alpha_compressed);
  CLEANUP_ALPHA:
     free (alpha);
  CLEANUP:
@@ -1411,12 +1408,13 @@ _cairo_pdf_surface_emit_image (cairo_pdf_surface_t   *surface,
                                cairo_pdf_resource_t  *image_ret)
 {
     cairo_status_t status = CAIRO_STATUS_SUCCESS;
-    char *rgb, *compressed;
-    unsigned long rgb_size, compressed_size;
+    char *rgb;
+    unsigned long rgb_size;
     uint32_t *pixel;
     int i, x, y;
     cairo_pdf_resource_t smask = {0}; /* squelch bogus compiler warning */
     cairo_bool_t need_smask;
+    cairo_output_stream_t *deflate;
 
     /* XXX: Need to rewrite this as a pdf_surface function with
      * pause/resume of content_stream, (currently the only caller does
@@ -1474,19 +1472,13 @@ _cairo_pdf_surface_emit_image (cairo_pdf_surface_t   *surface,
 	}
     }
 
-    compressed = compress_dup (rgb, rgb_size, &compressed_size);
-    if (compressed == NULL) {
-	status = _cairo_error (CAIRO_STATUS_NO_MEMORY);
-	goto CLEANUP_RGB;
-    }
-
     need_smask = FALSE;
     if (image->format == CAIRO_FORMAT_ARGB32 ||
 	image->format == CAIRO_FORMAT_A8 ||
 	image->format == CAIRO_FORMAT_A1) {
 	status = _cairo_pdf_surface_emit_smask (surface, image, &smask);
 	if (status)
-	    goto CLEANUP_COMPRESSED;
+	    goto CLEANUP_RGB;
 
 	if (smask.id)
 	    need_smask = TRUE;
@@ -1515,18 +1507,21 @@ _cairo_pdf_surface_emit_image (cairo_pdf_surface_t   *surface,
 						 IMAGE_DICTIONARY,
 						 image->width, image->height);
     if (status)
-	goto CLEANUP_COMPRESSED;
+	goto CLEANUP_RGB;
 
 #undef IMAGE_DICTIONARY
 
     *image_ret = surface->pdf_stream.self;
 
-    _cairo_output_stream_write (surface->output, compressed, compressed_size);
+    deflate = _cairo_deflate_stream_create (surface->output);
+    _cairo_output_stream_write (deflate, rgb, rgb_size);
+    status = _cairo_output_stream_destroy (deflate);
+    if (status)
+	goto CLEANUP_RGB;
+
     _cairo_output_stream_printf (surface->output, "\r\n");
     status = _cairo_pdf_surface_close_stream (surface);
 
-CLEANUP_COMPRESSED:
-    free (compressed);
 CLEANUP_RGB:
     free (rgb);
 CLEANUP:
-- 
1.5.3.8



More information about the cairo mailing list