summaryrefslogtreecommitdiff
path: root/gs/base/scf.h
diff options
context:
space:
mode:
Diffstat (limited to 'gs/base/scf.h')
-rw-r--r--gs/base/scf.h205
1 files changed, 205 insertions, 0 deletions
diff --git a/gs/base/scf.h b/gs/base/scf.h
new file mode 100644
index 000000000..cfcc54f33
--- /dev/null
+++ b/gs/base/scf.h
@@ -0,0 +1,205 @@
+/* Copyright (C) 2001-2006 Artifex Software, Inc.
+ All Rights Reserved.
+
+ This software is provided AS-IS with no warranty, either express or
+ implied.
+
+ This software is distributed under license and may not be copied, modified
+ or distributed except as expressly authorized under the terms of that
+ license. Refer to licensing information at http://www.artifex.com/
+ or contact Artifex Software, Inc., 7 Mt. Lassen Drive - Suite A-134,
+ San Rafael, CA 94903, U.S.A., +1(415)492-9861, for further information.
+*/
+
+/* $Id$ */
+/* Common definitions for CCITTFax encoding and decoding filters */
+
+#ifndef scf_INCLUDED
+# define scf_INCLUDED
+
+#include "shc.h"
+
+/*
+ * The CCITT Group 3 (T.4) and Group 4 (T.6) fax specifications map
+ * run lengths to Huffman codes. White and black have different mappings.
+ * If the run length is 64 or greater, two or more codes are needed:
+ * - One or more 'make-up' codes for 2560 pixels;
+ * - A 'make-up' code that encodes the multiple of 64;
+ * - A 'termination' code for the remainder.
+ * For runs of 63 or less, only the 'termination' code is needed.
+ */
+
+/* ------ Encoding tables ------ */
+
+/*
+ * The maximum possible length of a scan line is determined by the
+ * requirement that 3 runs have to fit into the stream buffer.
+ * A run of length N requires approximately ceil(N / 2560) makeup codes,
+ * hence 1.5 * ceil(N / 2560) bytes. Taking the largest safe stream
+ * buffer size as 32K, we arrive at the following maximum width:
+ */
+#if arch_sizeof_int > 2
+# define cfe_max_width (2560 * 32000 * 2 / 3)
+#else
+# define cfe_max_width (max_int - 40) /* avoid overflows */
+#endif
+/* The +5 in cfe_max_code_bytes is a little conservative. */
+#define cfe_max_code_bytes(width) ((width) / 2560 * 3 / 2 + 5)
+
+typedef hce_code cfe_run;
+
+/* Codes common to 1-D and 2-D encoding. */
+/* The decoding algorithms know that EOL is 0....01. */
+#define run_eol_code_length 12
+#define run_eol_code_value 1
+extern const cfe_run cf_run_eol;
+typedef struct cf_runs_s {
+ cfe_run termination[64];
+ cfe_run make_up[41];
+} cf_runs;
+extern const cf_runs
+ cf_white_runs, cf_black_runs;
+extern const cfe_run cf_uncompressed[6];
+extern const cfe_run cf_uncompressed_exit[10]; /* indexed by 2 x length of */
+
+ /* white run + (1 if next run black, 0 if white) */
+/* 1-D encoding. */
+extern const cfe_run cf1_run_uncompressed;
+
+/* 2-D encoding. */
+extern const cfe_run cf2_run_pass;
+
+#define cf2_run_pass_length 4
+#define cf2_run_pass_value 0x1
+#define cf2_run_vertical_offset 3
+extern const cfe_run cf2_run_vertical[7]; /* indexed by b1 - a1 + offset */
+extern const cfe_run cf2_run_horizontal;
+
+#define cf2_run_horizontal_value 1
+#define cf2_run_horizontal_length 3
+extern const cfe_run cf2_run_uncompressed;
+
+/* 2-D Group 3 encoding. */
+extern const cfe_run cf2_run_eol_1d;
+extern const cfe_run cf2_run_eol_2d;
+
+/* ------ Decoding tables ------ */
+
+typedef hcd_code cfd_node;
+
+#define run_length value
+
+/*
+ * The value in the decoding tables is either a white or black run length,
+ * or a (negative) exceptional value.
+ */
+#define run_error (-1)
+#define run_zeros (-2) /* EOL follows, possibly with more padding first */
+#define run_uncompressed (-3)
+/* 2-D codes */
+#define run2_pass (-4)
+#define run2_horizontal (-5)
+
+#define cfd_white_initial_bits 8
+#define cfd_white_min_bits 4 /* shortest white run */
+extern const cfd_node cf_white_decode[];
+
+#define cfd_black_initial_bits 7
+#define cfd_black_min_bits 2 /* shortest black run */
+extern const cfd_node cf_black_decode[];
+
+#define cfd_2d_initial_bits 7
+#define cfd_2d_min_bits 4 /* shortest non-H/V 2-D run */
+extern const cfd_node cf_2d_decode[];
+
+#define cfd_uncompressed_initial_bits 6 /* must be 6 */
+extern const cfd_node cf_uncompressed_decode[];
+
+/* ------ Run detection macros ------ */
+
+/*
+ * For the run detection macros:
+ * white_byte is 0 or 0xff for BlackIs1 or !BlackIs1 respectively;
+ * data holds p[-1], inverted if !BlackIs1;
+ * count is the number of valid bits remaining in the scan line.
+ */
+
+/* Aliases for bit processing tables. */
+#define cf_byte_run_length byte_bit_run_length_neg
+#define cf_byte_run_length_0 byte_bit_run_length_0
+
+/* Skip over white pixels to find the next black pixel in the input. */
+/* Store the run length in rlen, and update data, p, and count. */
+/* There are many more white pixels in typical input than black pixels, */
+/* and the runs of white pixels tend to be much longer, so we use */
+/* substantially different loops for the two cases. */
+
+#define skip_white_pixels(data, p, count, white_byte, rlen)\
+BEGIN\
+ rlen = cf_byte_run_length[count & 7][data ^ 0xff];\
+ if ( rlen >= 8 ) { /* run extends past byte boundary */\
+ if ( white_byte == 0 ) {\
+ if ( p[0] ) { data = p[0]; p += 1; rlen -= 8; }\
+ else if ( p[1] ) { data = p[1]; p += 2; }\
+ else {\
+ while ( !(p[2] | p[3] | p[4] | p[5]) )\
+ p += 4, rlen += 32;\
+ if ( p[2] ) {\
+ data = p[2]; p += 3; rlen += 8;\
+ } else if ( p[3] ) {\
+ data = p[3]; p += 4; rlen += 16;\
+ } else if ( p[4] ) {\
+ data = p[4]; p += 5; rlen += 24;\
+ } else /* p[5] */ {\
+ data = p[5]; p += 6; rlen += 32;\
+ }\
+ }\
+ } else {\
+ if ( p[0] != 0xff ) { data = (byte)~p[0]; p += 1; rlen -= 8; }\
+ else if ( p[1] != 0xff ) { data = (byte)~p[1]; p += 2; }\
+ else {\
+ while ( (p[2] & p[3] & p[4] & p[5]) == 0xff )\
+ p += 4, rlen += 32;\
+ if ( p[2] != 0xff ) {\
+ data = (byte)~p[2]; p += 3; rlen += 8;\
+ } else if ( p[3] != 0xff ) {\
+ data = (byte)~p[3]; p += 4; rlen += 16;\
+ } else if ( p[4] != 0xff ) {\
+ data = (byte)~p[4]; p += 5; rlen += 24;\
+ } else /* p[5] != 0xff */ {\
+ data = (byte)~p[5]; p += 6; rlen += 32;\
+ }\
+ }\
+ }\
+ rlen += cf_byte_run_length_0[data ^ 0xff];\
+ }\
+ count -= rlen;\
+END
+
+/* Skip over black pixels to find the next white pixel in the input. */
+/* Store the run length in rlen, and update data, p, and count. */
+
+#define skip_black_pixels(data, p, count, white_byte, rlen)\
+BEGIN\
+ rlen = cf_byte_run_length[count & 7][data];\
+ if ( rlen >= 8 ) {\
+ if ( white_byte == 0 )\
+ for ( ; ; p += 4, rlen += 32 ) {\
+ if ( p[0] != 0xff ) { data = p[0]; p += 1; rlen -= 8; break; }\
+ if ( p[1] != 0xff ) { data = p[1]; p += 2; break; }\
+ if ( p[2] != 0xff ) { data = p[2]; p += 3; rlen += 8; break; }\
+ if ( p[3] != 0xff ) { data = p[3]; p += 4; rlen += 16; break; }\
+ }\
+ else\
+ for ( ; ; p += 4, rlen += 32 ) {\
+ if ( p[0] ) { data = (byte)~p[0]; p += 1; rlen -= 8; break; }\
+ if ( p[1] ) { data = (byte)~p[1]; p += 2; break; }\
+ if ( p[2] ) { data = (byte)~p[2]; p += 3; rlen += 8; break; }\
+ if ( p[3] ) { data = (byte)~p[3]; p += 4; rlen += 16; break; }\
+ }\
+ rlen += cf_byte_run_length_0[data];\
+ }\
+ count -= rlen;\
+END
+
+#endif /* scf_INCLUDED */