diff options
author | Robin Watts <robin.watts@artifex.com> | 2012-08-01 17:13:23 +0100 |
---|---|---|
committer | Robin Watts <robin.watts@artifex.com> | 2012-08-02 14:59:55 +0100 |
commit | 974ba5dde88108ba54c10e8c4f2c59fbce2db5cd (patch) | |
tree | fd9139d37f749850d33c5d55db89e67b1982b9a6 | |
parent | fe9465d90b4662eb56c7d0686ea87603b5c238b3 (diff) | |
download | ghostpdl-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.c | 20 | ||||
-rw-r--r-- | gs/base/gsbitops.h | 4 | ||||
-rw-r--r-- | gs/base/gxclbits.c | 19 | ||||
-rw-r--r-- | gs/base/gxcldev.h | 3 | ||||
-rw-r--r-- | gs/base/gxclrast.c | 13 |
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. |