1
/* Copyright (C) 2001-2006 Artifex Software, Inc.
4
This software is provided AS-IS with no warranty, either express or
7
This software is distributed under license and may not be copied, modified
8
or distributed except as expressly authorized under the terms of that
9
license. Refer to licensing information at http://www.artifex.com/
10
or contact Artifex Software, Inc., 7 Mt. Lassen Drive - Suite A-134,
11
San Rafael, CA 94903, U.S.A., +1(415)492-9861, for further information.
14
/* $Id: sbhc.c 8250 2007-09-25 13:31:24Z giles $ */
15
/* Bounded Huffman code filters */
23
/* ------ BoundedHuffmanEncode ------ */
25
private_st_BHCE_state();
27
/* Initialize BoundedHuffmanEncode filter. */
29
s_BHCE_reinit(stream_state * st)
31
stream_BHCE_state *const ss = (stream_BHCE_state *) st;
33
ss->encode.count = ss->definition.num_values;
34
s_bhce_init_inline(ss);
38
s_BHCE_init(register stream_state * st)
40
stream_BHCE_state *const ss = (stream_BHCE_state *) st;
41
hce_code *encode = ss->encode.codes =
42
(hce_code *) gs_alloc_byte_array(st->memory,
43
ss->definition.num_values,
44
sizeof(hce_code), "BHCE encode");
49
hc_make_encoding(encode, &ss->definition);
50
return s_BHCE_reinit(st);
53
/* Release the filter. */
55
s_BHCE_release(stream_state * st)
57
stream_BHCE_state *const ss = (stream_BHCE_state *) st;
59
gs_free_object(st->memory, ss->encode.codes, "BHCE encode");
62
/* Process a buffer. */
64
s_BHCE_process(stream_state * st, stream_cursor_read * pr,
65
stream_cursor_write * pw, bool last)
67
stream_BHCE_state *const ss = (stream_BHCE_state *) st;
68
const byte *p = pr->ptr;
69
const byte *rlimit = pr->limit;
71
byte *wlimit = pw->limit - (hc_bits_size >> 3);
72
const hce_code *encode = ss->encode.codes;
73
uint num_values = ss->definition.num_values;
74
uint zero_runs = ss->EncodeZeroRuns;
75
uint zero_max = num_values - zero_runs + (ss->EndOfData ? 0 : 1);
76
uint zero_value = (zero_max > 1 ? 0 : 0x100);
77
int zeros = ss->zeros;
83
while (p < rlimit && q < wlimit) {
87
if (value >= num_values) {
91
if (value == zero_value) { /* Accumulate a run of zeros. */
93
if (zeros != zero_max)
95
/* We've scanned the longest run we can encode. */
96
cp = &encode[zeros - 2 + zero_runs];
98
hc_put_code((stream_hc_state *) ss, q, cp);
101
/* Check whether we need to put out a zero run. */
104
cp = (zeros == 1 ? &encode[0] :
105
&encode[zeros - 2 + zero_runs]);
107
hc_put_code((stream_hc_state *) ss, q, cp);
111
hc_put_code((stream_hc_state *) ss, q, cp);
116
if (last && status == 0) {
117
if (zeros > 0) { /* Put out a final run of zeros. */
118
const hce_code *cp = (zeros == 1 ? &encode[0] :
119
&encode[zeros - 2 + zero_runs]);
121
if (!hce_bits_available(cp->code_length))
124
hc_put_code((stream_hc_state *) ss, q, cp);
128
if (ss->EndOfData) { /* Put out the EOD code if we have room. */
129
const hce_code *cp = &encode[num_values - 1];
131
if (!hce_bits_available(cp->code_length))
134
hc_put_code((stream_hc_state *) ss, q, cp);
140
q = hc_put_last_bits((stream_hc_state *) ss, q);
148
return (p == rlimit ? 0 : 1);
151
/* Stream template */
152
const stream_template s_BHCE_template =
153
{&st_BHCE_state, s_BHCE_init, s_BHCE_process,
154
1, hc_bits_size >> 3, s_BHCE_release, NULL, s_BHCE_reinit
157
/* ------ BoundedHuffmanDecode ------ */
159
private_st_BHCD_state();
161
#define hcd_initial_bits 7 /* arbitrary, >= 1 and <= 8 */
163
/* Initialize BoundedHuffmanDecode filter. */
165
s_BHCD_reinit(stream_state * st)
167
stream_BHCD_state *const ss = (stream_BHCD_state *) st;
169
ss->decode.count = ss->definition.num_values;
170
s_bhcd_init_inline(ss);
174
s_BHCD_init(register stream_state * st)
176
stream_BHCD_state *const ss = (stream_BHCD_state *) st;
177
uint initial_bits = ss->decode.initial_bits =
178
min(hcd_initial_bits, ss->definition.num_counts);
179
uint dsize = hc_sizeof_decoding(&ss->definition, initial_bits);
180
hcd_code *decode = ss->decode.codes =
181
(hcd_code *) gs_alloc_byte_array(st->memory, dsize,
182
sizeof(hcd_code), "BHCD decode");
186
/****** WRONG ******/
187
hc_make_decoding(decode, &ss->definition, initial_bits);
189
return s_BHCD_reinit(st);
192
/* Release the filter. */
194
s_BHCD_release(stream_state * st)
196
stream_BHCD_state *const ss = (stream_BHCD_state *) st;
198
gs_free_object(st->memory, ss->decode.codes, "BHCD decode");
201
/* Process a buffer. */
203
s_BHCD_process(stream_state * st, stream_cursor_read * pr,
204
stream_cursor_write * pw, bool last)
206
stream_BHCD_state *const ss = (stream_BHCD_state *) st;
210
byte *wlimit = pw->limit;
211
const hcd_code *decode = ss->decode.codes;
212
uint initial_bits = ss->decode.initial_bits;
213
uint zero_runs = ss->EncodeZeroRuns;
215
int eod = (ss->EndOfData ? ss->definition.num_values - 1 : -1);
218
z:for (; zeros > 0; --zeros) {
229
hcd_ensure_bits(initial_bits, x1);
230
cp = &decode[hcd_peek_var_bits(initial_bits)];
231
w1:if (q >= wlimit) {
235
if ((clen = cp->code_length) > initial_bits) {
236
if (!hcd_bits_available(clen)) { /* We don't have enough bits for */
237
/* all possible codes that begin this way, */
238
/* but we might have enough for */
240
/****** NOT IMPLEMENTED YET ******/
243
clen -= initial_bits;
244
hcd_skip_bits(initial_bits);
245
hcd_ensure_bits(clen, out); /* can't exit */
246
cp = &decode[cp->value + hcd_peek_var_bits(clen)];
247
hcd_skip_bits(cp->code_length);
251
if (cp->value >= zero_runs) {
252
if (cp->value == eod) {
256
/* This code represents a run of zeros, */
257
/* not a single output value. */
258
zeros = cp->value - zero_runs + 2;
263
/* We don't have enough bits for all possible */
264
/* codes, but we might have enough for */
266
x1:cp = &decode[(bits & ((1 << bits_left) - 1)) <<
267
(initial_bits - bits_left)];
268
if ((clen = cp->code_length) <= bits_left)
272
out:bhcd_store_state();
277
/* Stream template */
278
const stream_template s_BHCD_template =
279
{&st_BHCD_state, s_BHCD_init, s_BHCD_process, 1, 1, s_BHCD_release,