summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorRobin Watts <robin.watts@artifex.com>2012-08-01 17:13:23 +0100
committerRobin Watts <robin.watts@artifex.com>2012-08-02 14:59:55 +0100
commit974ba5dde88108ba54c10e8c4f2c59fbce2db5cd (patch)
treefd9139d37f749850d33c5d55db89e67b1982b9a6
parentfe9465d90b4662eb56c7d0686ea87603b5c238b3 (diff)
downloadghostpdl-974ba5dde88108ba54c10e8c4f2c59fbce2db5cd.tar.gz
Add new 'const' compression method for clist bits.
Spot that the compressed bitmap is all identically the same byte value (most likely 0 or FF), and if so, send just a single byte.
-rw-r--r--gs/base/gsbitops.c20
-rw-r--r--gs/base/gsbitops.h4
-rw-r--r--gs/base/gxclbits.c19
-rw-r--r--gs/base/gxcldev.h3
-rw-r--r--gs/base/gxclrast.c13
5 files changed, 50 insertions, 9 deletions
diff --git a/gs/base/gsbitops.c b/gs/base/gsbitops.c
index 6f26a8faf..e618c85dd 100644
--- a/gs/base/gsbitops.c
+++ b/gs/base/gsbitops.c
@@ -661,6 +661,26 @@ bytes_copy_rectangle(byte * dest, uint dest_raster,
}
}
+int
+bytes_rectangle_is_const(const byte * src, uint src_raster,
+ int width_bytes, int height)
+{
+ int i;
+ char c;
+
+ if (width_bytes == 0 || height == 0)
+ return -1;
+ c = *src;
+ while (height-- > 0) {
+ const byte *s = src;
+ src += src_raster;
+ for (i = width_bytes; i > 0; i--)
+ if (*s++ != c)
+ return -1;
+ }
+ return c;
+}
+
/* Copy a rectangle of bytes zeroing any padding bytes. */
void
bytes_copy_rectangle_zero_padding(byte * dest, uint dest_raster,
diff --git a/gs/base/gsbitops.h b/gs/base/gsbitops.h
index 6db7c9d49..fedeef23d 100644
--- a/gs/base/gsbitops.h
+++ b/gs/base/gsbitops.h
@@ -326,6 +326,10 @@ void bytes_fill_rectangle(byte * dest, uint raster,
void bytes_copy_rectangle(byte * dest, uint dest_raster,
const byte * src, uint src_raster, int width_bytes, int height);
+/* Check if a rectangle of bytes are a constant value. Returns 0..255 (the
+ constant value) if it is constant, or -1 otherwise. */
+int bytes_rectangle_is_const(const byte * src, uint src_raster, int width_bytes, int height);
+
/* Copy a rectangle of bytes, ensuring that any padding bits at the end
* of each dest_raster line are zeroed. */
void bytes_copy_rectangle_zero_padding(byte * dest, uint dest_raster,
diff --git a/gs/base/gxclbits.c b/gs/base/gxclbits.c
index fe33150ed..8934e04fb 100644
--- a/gs/base/gxclbits.c
+++ b/gs/base/gxclbits.c
@@ -130,6 +130,7 @@ cmd_put_bits(gx_device_clist_writer * cldev, gx_clist_state * pcls,
gs_memory_t *mem = cldev->memory;
byte *dp;
int compress = 0;
+ int code;
/*
* See if compressing the bits is possible and worthwhile.
@@ -138,7 +139,7 @@ cmd_put_bits(gx_device_clist_writer * cldev, gx_clist_state * pcls,
* in the buffer and decompress_elsewhere isn't set.
*/
if (short_size >= 50 &&
- (compression_mask & cmd_mask_compress_any) != 0 &&
+ (compression_mask & ((1<<cmd_compress_rle) | (1<<cmd_compress_cfe))) != 0 &&
(uncompressed_size <= max_size ||
(compression_mask & decompress_elsewhere) != 0)
) {
@@ -147,7 +148,6 @@ cmd_put_bits(gx_device_clist_writer * cldev, gx_clist_state * pcls,
stream_CFE_state cf;
stream_RLE_state rl;
} sstate;
- int code;
int try_size = op_size + min(uncompressed_size, max_size);
*psize = try_size;
@@ -221,8 +221,6 @@ cmd_put_bits(gx_device_clist_writer * cldev, gx_clist_state * pcls,
} else if (uncompressed_size > max_size)
return_error(gs_error_limitcheck);
else {
- int code;
-
*psize = op_size + short_size;
code = (pcls != 0 ?
set_cmd_put_op(dp, cldev, pcls, 0, *psize) :
@@ -231,8 +229,17 @@ cmd_put_bits(gx_device_clist_writer * cldev, gx_clist_state * pcls,
return code;
cmd_uncount_op(0, *psize);
}
- bytes_copy_rectangle(dp + op_size, short_raster, data, raster,
- short_raster, height);
+ if ((compression_mask & (1 << cmd_compress_const)) &&
+ (code = bytes_rectangle_is_const(data, raster, uncompressed_raster << 3, height)) >= 0) {
+ cmd_shorten_list_op(cldev,
+ (pcls ? &pcls->list : &cldev->band_range_list),
+ *psize - (op_size + 1));
+ *psize = op_size + 1;
+ dp[op_size] = code;
+ compress = cmd_compress_const;
+ } else
+ bytes_copy_rectangle(dp + op_size, short_raster, data, raster,
+ short_raster, height);
out:
*pdp = dp;
return compress;
diff --git a/gs/base/gxcldev.h b/gs/base/gxcldev.h
index 54dc2034b..a43c7e20e 100644
--- a/gs/base/gxcldev.h
+++ b/gs/base/gxcldev.h
@@ -37,8 +37,9 @@
/*#define cmd_compress_none 0 *//* (implicit) */
#define cmd_compress_rle 1
#define cmd_compress_cfe 2
+#define cmd_compress_const 3
#define cmd_mask_compress_any\
- ((1 << cmd_compress_rle) | (1 << cmd_compress_cfe))
+ ((1 << cmd_compress_rle) | (1 << cmd_compress_cfe) | (1 << cmd_compress_const))
/* Exported by gxclutil.c */
void clist_rle_init(stream_RLE_state *ss);
void clist_rld_init(stream_RLD_state *ss);
diff --git a/gs/base/gxclrast.c b/gs/base/gxclrast.c
index 87ee4c74a..373ee9788 100644
--- a/gs/base/gxclrast.c
+++ b/gs/base/gxclrast.c
@@ -1021,7 +1021,12 @@ in: /* Initialize for a new page. */
}
compression = *cbp++;
}
- if (compression) { /* Decompress the image data. */
+ if (compression == cmd_compress_const) {
+ cbp = cmd_read_data(&cbuf, plane_bits, 1, cbp);
+ if (width_bytes > 0 && state.rect.height > 0)
+ memset(plane_bits+1, *plane_bits, width_bytes * state.rect.height - 1);
+
+ } else if (compression) { /* Decompress the image data. */
stream_cursor_read r;
stream_cursor_write w;
@@ -2386,7 +2391,11 @@ read_set_bits(command_buf_t *pcb, tile_slot *bits, int compress,
#ifdef DEBUG
slot->index = pcls->tile_index;
#endif
- if (compress) {
+ if (compress == cmd_compress_const) {
+ cbp = cmd_read_data(pcb, data, 1, cbp);
+ if (width_bytes > 0 && rep_height > 0)
+ memset(data+1, *data, width_bytes * rep_height - 1);
+ } else if (compress) {
/*
* Decompress the image data. We'd like to share this code with the
* similar code in copy_*, but right now we don't see how.