summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorHenry Stiles <henry.stiles@artifex.com>2012-02-02 12:14:41 -0700
committerChris Liddell <chris.liddell@artifex.com>2012-03-15 11:54:20 +0000
commitd01ab6457920cb6e54fcc9c4229cd09bc4ac2571 (patch)
treefff8bf0a0a261ab6e0171adcf23ddc1370b8ea00
parent20bba4c40374d7f5c85d934df5c34ff7da9f8735 (diff)
Add 4 new raster decompression methods to PCL.
HPGL/2 and RTL plotters support the following decompression methods: uncompressed block (#4), CCITT group 3 1 dimensional (#6), CCITT group 3 2 dimensional (#7), CCITT group 4 2 dimensional (#8). These have gotten little testing we only have a couple test files at the current time.
-rw-r--r--pcl/pcl.mak6
-rw-r--r--pcl/rtgmode.c5
-rw-r--r--pcl/rtraster.c130
-rw-r--r--pcl/rtrstcmp.c2
-rw-r--r--pcl/rtrstcmp.h24
5 files changed, 152 insertions, 15 deletions
diff --git a/pcl/pcl.mak b/pcl/pcl.mak
index 9490c83c4..caa0dd8ad 100644
--- a/pcl/pcl.mak
+++ b/pcl/pcl.mak
@@ -351,6 +351,9 @@ $(PCLOBJ)rtmisc.$(OBJ): $(PCLSRC)rtmisc.c \
# Chapter 15
$(PCLOBJ)rtraster.$(OBJ): $(PCLSRC)rtraster.c \
$(memory__h) \
+ $(strimpl_h) \
+ $(scfx_h) \
+ $(stream_h) \
$(gx_h) \
$(gsmatrix_h) \
$(gscoord_h) \
@@ -367,6 +370,7 @@ $(PCLOBJ)rtraster.$(OBJ): $(PCLSRC)rtraster.c \
$(pcindxed_h) \
$(pcwhtidx_h) \
$(pcdraw_h) \
+ $(plvalue_h) \
$(rtgmode_h) \
$(rtrstcmp_h) \
$(rtraster_h)
@@ -582,7 +586,7 @@ $(PCLOBJ)rtgmode.$(OBJ): $(PCLSRC)rtgmode.c \
$(PCLCCC) $(PCLSRC)rtgmode.c $(PCLO_)rtgmode.$(OBJ)
$(PCLOBJ)rtrstcmp.$(OBJ): $(PCLSRC)rtrstcmp.c \
- $(string__h) \
+ $(string__h) \
$(pcstate_h) \
$(rtrstcmp_h)
$(PCLCCC) $(PCLSRC)rtrstcmp.c $(PCLO_)rtrstcmp.$(OBJ)
diff --git a/pcl/rtgmode.c b/pcl/rtgmode.c
index a9b2a40e3..d0f7a165b 100644
--- a/pcl/rtgmode.c
+++ b/pcl/rtgmode.c
@@ -506,9 +506,10 @@ set_compression_method(
{
uint mode = uint_arg(pargs);
- if ( (mode < count_of(pcl_decomp_proc)) &&
- ((pcl_decomp_proc[mode] != 0) || (mode == (uint)ADAPTIVE_COMPRESS)) )
+ if (mode < count_of(pcl_decomp_proc))
pcs->raster_state.compression_mode = mode;
+ else
+ return gs_throw1(e_Range, "unsupported mode %d\n", mode);
return 0;
}
diff --git a/pcl/rtraster.c b/pcl/rtraster.c
index 840c2ac76..73af06754 100644
--- a/pcl/rtraster.c
+++ b/pcl/rtraster.c
@@ -14,6 +14,9 @@
/* rtraster.c - raster transfer commands */
#include "memory_.h"
+#include "strimpl.h"
+#include "scfx.h"
+#include "stream.h"
#include "gx.h"
#include "gsmatrix.h"
#include "gscoord.h"
@@ -30,6 +33,7 @@
#include "pcindxed.h"
#include "pcwhtidx.h"
#include "pcdraw.h"
+#include "plvalue.h"
#include "rtgmode.h"
#include "rtrstcmp.h"
#include "rtraster.h"
@@ -253,7 +257,7 @@ gen_mask_1byte(
* pixel. The only possible such case in PCL is 8-bits per primary 3 color,
* so this routine handles only that case.
*/
- void
+ static void
gen_mask_multibyte(
pcl_raster_t * prast
)
@@ -914,6 +918,118 @@ process_row(
}
/*
+ * Process an input data buffer using no compression with blocks (multiple rows)
+ */
+
+ static int
+process_block_nocompress(
+ gs_state * pgs,
+ pcl_raster_t * prast,
+ const byte * pin,
+ uint insize
+)
+{
+ uint32 row_bytes, nrows;
+ pcl_seed_row_t *pseed_row = prast->pseed_rows;
+ byte *p;
+
+ /* the size of the rows are stored in the first 4 bytes */
+ if (insize < 4) {
+ return gs_throw(e_Range, "Size of raster cannot be determined\n");
+ }
+
+ row_bytes = (pl_get_uint32(pin) * prast->bits_per_plane + 7) / 8;
+
+ /* the remaining data after the row size should be divisible by
+ the row length to have equal sized rows */
+ if ((insize - 4) % row_bytes)
+ return gs_throw(e_Range, "Non integral number of rows in raster\n");
+
+ nrows = insize / row_bytes;
+
+ for (p = (byte *)pin + 4; nrows > 0; p += row_bytes, nrows--) {
+ int code;
+ pcl_decomp_proc[0](pseed_row, p, row_bytes);
+ prast->plane_index = 1;
+ code = process_row(prast, 0);
+ if (code < 0)
+ return gs_rethrow(code, "Raster row processing failed\n");
+ }
+ return 0;
+}
+
+static int
+pcl_ccitt_error(stream_state * st, const char *str)
+{
+ (void) gs_throw1(-1, "%s", str);
+ return 0;
+}
+
+
+static int
+process_ccitt_compress(
+ gs_state * pgs,
+ pcl_raster_t * prast,
+ const byte * pin,
+ uint insize,
+ pcl_rast_buff_type_t comp
+
+)
+{
+ stream_CFD_state state;
+ stream_cursor_read scr;
+ stream_cursor_write scw;
+ pcl_seed_row_t *pout = prast->pseed_rows;
+
+ if (insize < 4)
+ return gs_throw(e_Range, "raster row size not specified");
+ s_init_state((stream_state*)&state, &s_CFD_template, prast->pmem);
+ state.report_error = pcl_ccitt_error;
+ s_CFD_template.set_defaults((stream_state*)&state);
+ state.EndOfLine = false;
+ state.EndOfBlock = false;
+ state.Columns = pl_get_uint32(pin);
+ state.Rows = 0; /* undetermined */
+ if (comp == CCITT_GR3_1D_COMPRESS)
+ state.K = 0;
+ else if (comp == CCITT_GR3_2D_COMPRESS)
+ state.K = 1;
+ else
+ state.K = -1;
+ s_CFD_template.init((stream_state*)&state);
+ scr.ptr = pin + 4 - 1;
+ scr.limit = scr.ptr + insize;
+ scw.ptr = pout->pdata - 1;
+ scw.limit = scw.ptr + (state.Columns + 7) / 8;
+
+ while (1) {
+ int code = s_CFD_template.process((stream_state*)&state, &scr, &scw, true);
+ switch (code) {
+
+ case 1: /* need output, process the scanline and continue. */
+ scw.ptr = pout->pdata - 1;
+ scw.limit = scw.ptr + (state.Columns + 7) / 8;
+ process_row(prast, 0);
+ break;
+ case EOFC: /* all done */
+ s_CFD_template.release((stream_state*)&state);
+ return 0;
+ case 0: /* need input is an error - we've given it all the data */
+ case ERRC: /* error */
+ s_CFD_template.release((stream_state*)&state);
+ return gs_rethrow(e_Range, "CCITT decompression failed\n");
+ default:
+ return gs_throw(e_Range, "unknown code CCITT decompression\n");
+ }
+ }
+ /* not reached */
+ return -1;
+}
+
+
+
+
+/*
* Process an input data buffer using adpative compression.
*/
static int
@@ -1050,12 +1166,16 @@ add_raster_plane(
pcl_seed_row_t * pseed = prast->pseed_rows + plane_index;
prast->plane_index++;
- if (comp_mode == ADAPTIVE_COMPRESS)
+ if (!PCL_BLOCK_COMP(comp_mode))
+ (void)pcl_decomp_proc[comp_mode](pseed, pdata, nbytes);
+ else if (comp_mode == NO_COMPRESS_BLOCK)
+ return process_block_nocompress(pcs->pgs, prast, pdata, nbytes);
+ else if (comp_mode == ADAPTIVE_COMPRESS)
return process_adaptive_compress(pcs->pgs, prast, pdata, nbytes);
else
- (void)pcl_decomp_proc[comp_mode](pseed, pdata, nbytes);
+ return process_ccitt_compress(pcs->pgs, prast, pdata, nbytes, comp_mode);
+
}
-
return 0;
}
@@ -1339,7 +1459,7 @@ transfer_raster_row(
code = add_raster_plane(pdata, arg_data_size(pargs), true, pcs);
/* complete the row (execpt for adaptive compression) */
- if (comp_mode != ADAPTIVE_COMPRESS && code == 0)
+ if (!PCL_BLOCK_COMP(comp_mode) && code == 0)
code = process_row((pcl_raster_t *)pcs->raster_state.pcur_raster, comp_mode);
return code;
diff --git a/pcl/rtrstcmp.c b/pcl/rtrstcmp.c
index fcddedd5c..d4998743f 100644
--- a/pcl/rtrstcmp.c
+++ b/pcl/rtrstcmp.c
@@ -255,6 +255,6 @@ void (*const pcl_decomp_proc[9 + 1])( pcl_seed_row_t * pout,
uncompress_1,
uncompress_2,
uncompress_3,
- 0, 0, 0, 0, 0, /* modes 4 and 6 - 8 unused; mode 5 handled separately */
+ 0, 0, 0, 0, 0, /* modes 4 - 8 handled separately */
uncompress_9
};
diff --git a/pcl/rtrstcmp.h b/pcl/rtrstcmp.h
index e9b34c378..ab8ad2fb1 100644
--- a/pcl/rtrstcmp.h
+++ b/pcl/rtrstcmp.h
@@ -26,8 +26,11 @@
* 1 - compression mode 1 (run length compression), param is size in bytes
* 2 - compression mode 2 ("Packbits" compression), param is size in bytes
* 3 - compression mode 3 (delta row compression), param is size in bytes
- * 4 - not used
+ * 4 - compression mode 4 (no compression blocks), param is size in bytes
* 5 - compression mode 5 (adaptive), param is size in bytes
+ * 6 - compression mode 5 (ccitt group 3 1d), param is size in bytes
+ * 7 - compression mode 5 (ccitt group 3 2d), param is size in bytes
+ * 8 - compression mode 5 (ccitt group 4 2d), param is size in bytes
* 9 - compression mode 9 (modified delta row), param is size in bytes
*
* There is no separate format for repeated rows. The desired effect can be
@@ -38,13 +41,22 @@ typedef enum {
RUN_LEN_COMPRESS = 1,
PACKBITS_COMPRESS = 2,
DELTA_ROW_COMPRESS = 3,
- /* 4 is not used, and indicated as reserved by HP */
+ NO_COMPRESS_BLOCK = 4,
ADAPTIVE_COMPRESS = 5,
- /* 6 - 8 unused */
+ CCITT_GR3_1D_COMPRESS = 6,
+ CCITT_GR3_2D_COMPRESS = 7,
+ CCITT_GR4_COMPRESS = 8,
MOD_DELTA_ROW_COMPRESS = 9
} pcl_rast_buff_type_t;
/*
+ * Identify the compression schemes that are block (not scan line
+ * oriented)
+ */
+
+#define PCL_BLOCK_COMP(comp) ((comp) >= NO_COMPRESS_BLOCK && (comp) <= CCITT_GR4_COMPRESS)
+
+/*
* A seed-row structure. These buffers are used both to pass data to the
* graphic library image routines, and to retain information on the last row
* sent to support "delta-row" compression.
@@ -82,8 +94,8 @@ typedef struct pcl_seed_row_s {
* The array of decompression functions.
*/
extern void (*const pcl_decomp_proc[9 + 1])(pcl_seed_row_t *pout,
- const byte *pin,
- int in_size
- );
+ const byte *pin,
+ int in_size
+ );
#endif /* rtrstcmp_INCLUDED */