1 /* Copyright (C) 1995, 1996, 1998, 1999 Aladdin Enterprises. All rights reserved.
2
3 This software is provided AS-IS with no warranty, either express or
4 implied.
5
6 This software is distributed under license and may not be copied,
7 modified or distributed except as expressly authorized under the terms
8 of the license contained in the file LICENSE in this distribution.
9
10 For more information about licensing, please refer to
11 http://www.ghostscript.com/licensing/. For information on
12 commercial licensing, go to http://www.artifex.com/licensing/ or
13 contact Artifex Software, Inc., 101 Lucas Valley Road #110,
14 San Rafael, CA 94903, U.S.A., +1(415)492-9861.
15 */
16
17 /* $Id: zfilterx.c,v 1.4 2002/02/21 22:24:54 giles Exp $ */
18 /* Extended (non-standard) filter creation */
19 #include "memory_.h"
20 #include "ghost.h"
21 #include "oper.h"
22 #include "gsstruct.h"
23 #include "ialloc.h"
24 #include "idict.h"
25 #include "idparam.h"
26 #include "store.h"
27 #include "strimpl.h"
28 #include "sfilter.h"
29 #include "sbwbs.h"
30 #include "sbhc.h"
31 #include "sbtx.h"
32 #include "shcgen.h"
33 #include "smtf.h"
34 #include "ifilter.h"
35
36 /* ------ Bounded Huffman code filters ------ */
37
38 /* Common setup for encoding and decoding filters */
39 private int
bhc_setup(os_ptr op,stream_BHC_state * pbhcs)40 bhc_setup(os_ptr op, stream_BHC_state * pbhcs)
41 {
42 int code;
43 int num_counts;
44 int data[max_hc_length + 1 + 256 + max_zero_run + 1];
45 uint dsize;
46 int i;
47 uint num_values, accum;
48 ushort *counts;
49 ushort *values;
50
51 check_type(*op, t_dictionary);
52 check_dict_read(*op);
53 if ((code = dict_bool_param(op, "FirstBitLowOrder", false,
54 &pbhcs->FirstBitLowOrder)) < 0 ||
55 (code = dict_int_param(op, "MaxCodeLength", 1, max_hc_length,
56 max_hc_length, &num_counts)) < 0 ||
57 (code = dict_bool_param(op, "EndOfData", true,
58 &pbhcs->EndOfData)) < 0 ||
59 (code = dict_uint_param(op, "EncodeZeroRuns", 2, 256,
60 256, &pbhcs->EncodeZeroRuns)) < 0 ||
61 /* Note: the code returned from the following call */
62 /* is actually the number of elements in the array. */
63 (code = dict_int_array_param(op, "Tables", countof(data),
64 data)) <= 0
65 )
66 return (code < 0 ? code : gs_note_error(e_rangecheck));
67 dsize = code;
68 if (dsize <= num_counts + 2)
69 return_error(e_rangecheck);
70 for (i = 0, num_values = 0, accum = 0; i <= num_counts;
71 i++, accum <<= 1
72 ) {
73 int count = data[i];
74
75 if (count < 0)
76 return_error(e_rangecheck);
77 num_values += count;
78 accum += count;
79 }
80 if (dsize != num_counts + 1 + num_values ||
81 accum != 1 << (num_counts + 1) ||
82 pbhcs->EncodeZeroRuns >
83 (pbhcs->EndOfData ? num_values - 1 : num_values)
84 )
85 return_error(e_rangecheck);
86 for (; i < num_counts + 1 + num_values; i++) {
87 int value = data[i];
88
89 if (value < 0 || value >= num_values)
90 return_error(e_rangecheck);
91 }
92 pbhcs->definition.counts = counts =
93 (ushort *) ialloc_byte_array(num_counts + 1, sizeof(ushort),
94 "bhc_setup(counts)");
95 pbhcs->definition.values = values =
96 (ushort *) ialloc_byte_array(num_values, sizeof(ushort),
97 "bhc_setup(values)");
98 if (counts == 0 || values == 0) {
99 ifree_object(values, "bhc_setup(values)");
100 ifree_object(counts, "bhc_setup(counts)");
101 return_error(e_VMerror);
102 }
103 for (i = 0; i <= num_counts; i++)
104 counts[i] = data[i];
105 pbhcs->definition.counts = counts;
106 pbhcs->definition.num_counts = num_counts;
107 for (i = 0; i < num_values; i++)
108 values[i] = data[i + num_counts + 1];
109 pbhcs->definition.values = values;
110 pbhcs->definition.num_values = num_values;
111 return 0;
112 }
113
114 /* <target> <dict> BoundedHuffmanEncode/filter <file> */
115 private int
zBHCE(i_ctx_t * i_ctx_p)116 zBHCE(i_ctx_t *i_ctx_p)
117 {
118 os_ptr op = osp;
119 stream_BHCE_state bhcs;
120 int code = bhc_setup(op, (stream_BHC_state *)&bhcs);
121
122 if (code < 0)
123 return code;
124 return filter_write(op, 0, &s_BHCE_template, (stream_state *)&bhcs, 0);
125 }
126
127 /* <source> <dict> BoundedHuffmanDecode/filter <file> */
128 private int
zBHCD(i_ctx_t * i_ctx_p)129 zBHCD(i_ctx_t *i_ctx_p)
130 {
131 os_ptr op = osp;
132 stream_BHCD_state bhcs;
133 int code = bhc_setup(op, (stream_BHC_state *)&bhcs);
134
135 if (code < 0)
136 return code;
137 return filter_read(i_ctx_p, 0, &s_BHCD_template, (stream_state *)&bhcs, 0);
138 }
139
140 /* <array> <max_length> .computecodes <array> */
141 /* The first max_length+1 elements of the array will be filled in with */
142 /* the code counts; the remaining elements will be replaced with */
143 /* the code values. This is the form needed for the Tables element of */
144 /* the dictionary parameter for the BoundedHuffman filters. */
145 private int
zcomputecodes(i_ctx_t * i_ctx_p)146 zcomputecodes(i_ctx_t *i_ctx_p)
147 {
148 os_ptr op = osp;
149 os_ptr op1 = op - 1;
150 uint asize;
151 hc_definition def;
152 ushort *data;
153 long *freqs;
154 int code = 0;
155
156 check_type(*op, t_integer);
157 check_write_type(*op1, t_array);
158 asize = r_size(op1);
159 if (op->value.intval < 1 || op->value.intval > max_hc_length)
160 return_error(e_rangecheck);
161 def.num_counts = op->value.intval;
162 if (asize < def.num_counts + 2)
163 return_error(e_rangecheck);
164 def.num_values = asize - (def.num_counts + 1);
165 data = (ushort *) gs_alloc_byte_array(imemory, asize, sizeof(ushort),
166 "zcomputecodes");
167 freqs = (long *)gs_alloc_byte_array(imemory, def.num_values,
168 sizeof(long),
169 "zcomputecodes(freqs)");
170
171 if (data == 0 || freqs == 0)
172 code = gs_note_error(e_VMerror);
173 else {
174 uint i;
175
176 def.counts = data;
177 def.values = data + (def.num_counts + 1);
178 for (i = 0; i < def.num_values; i++) {
179 const ref *pf = op1->value.const_refs + i + def.num_counts + 1;
180
181 if (!r_has_type(pf, t_integer)) {
182 code = gs_note_error(e_typecheck);
183 break;
184 }
185 freqs[i] = pf->value.intval;
186 }
187 if (!code) {
188 code = hc_compute(&def, freqs, imemory);
189 if (code >= 0) {
190 /* Copy back results. */
191 for (i = 0; i < asize; i++)
192 make_int(op1->value.refs + i, data[i]);
193 }
194 }
195 }
196 gs_free_object(imemory, freqs, "zcomputecodes(freqs)");
197 gs_free_object(imemory, data, "zcomputecodes");
198 if (code < 0)
199 return code;
200 pop(1);
201 return code;
202 }
203
204 /* ------ Burrows/Wheeler block sorting filters ------ */
205
206 /* Common setup for encoding and decoding filters */
207 private int
bwbs_setup(os_ptr op,stream_BWBS_state * pbwbss)208 bwbs_setup(os_ptr op, stream_BWBS_state * pbwbss)
209 {
210 int code =
211 dict_int_param(op, "BlockSize", 1, max_int / sizeof(int) - 10, 16384,
212 &pbwbss->BlockSize);
213
214 if (code < 0)
215 return code;
216 return 0;
217 }
218
219 /* <target> <dict> BWBlockSortEncode/filter <file> */
220 private int
zBWBSE(i_ctx_t * i_ctx_p)221 zBWBSE(i_ctx_t *i_ctx_p)
222 {
223 os_ptr op = osp;
224 stream_BWBSE_state bwbss;
225 int code;
226
227 check_type(*op, t_dictionary);
228 check_dict_read(*op);
229 code = bwbs_setup(op, (stream_BWBS_state *)&bwbss);
230 if (code < 0)
231 return code;
232 return filter_write(op, 0, &s_BWBSE_template, (stream_state *)&bwbss, 0);
233 }
234
235 /* <source> <dict> BWBlockSortDecode/filter <file> */
236 private int
zBWBSD(i_ctx_t * i_ctx_p)237 zBWBSD(i_ctx_t *i_ctx_p)
238 {
239 os_ptr op = osp;
240 stream_BWBSD_state bwbss;
241 int code = bwbs_setup(op, (stream_BWBS_state *)&bwbss);
242
243 if (code < 0)
244 return code;
245 return filter_read(i_ctx_p, 0, &s_BWBSD_template, (stream_state *)&bwbss, 0);
246 }
247
248 /* ------ Byte translation filters ------ */
249
250 /* Common setup */
251 private int
bt_setup(os_ptr op,stream_BT_state * pbts)252 bt_setup(os_ptr op, stream_BT_state * pbts)
253 {
254 check_read_type(*op, t_string);
255 if (r_size(op) != 256)
256 return_error(e_rangecheck);
257 memcpy(pbts->table, op->value.const_bytes, 256);
258 return 0;
259 }
260
261 /* <target> <table> ByteTranslateEncode/filter <file> */
262 /* <target> <table> <dict> ByteTranslateEncode/filter <file> */
263 private int
zBTE(i_ctx_t * i_ctx_p)264 zBTE(i_ctx_t *i_ctx_p)
265 {
266 os_ptr op = osp;
267 stream_BT_state bts;
268 int code = bt_setup(op, &bts);
269
270 if (code < 0)
271 return code;
272 return filter_write(op, 0, &s_BTE_template, (stream_state *)&bts, 0);
273 }
274
275 /* <target> <table> ByteTranslateDecode/filter <file> */
276 /* <target> <table> <dict> ByteTranslateDecode/filter <file> */
277 private int
zBTD(i_ctx_t * i_ctx_p)278 zBTD(i_ctx_t *i_ctx_p)
279 {
280 os_ptr op = osp;
281 stream_BT_state bts;
282 int code = bt_setup(op, &bts);
283
284 if (code < 0)
285 return code;
286 return filter_read(i_ctx_p, 0, &s_BTD_template, (stream_state *)&bts, 0);
287 }
288
289 /* ------ Move-to-front filters ------ */
290
291 /* <target> MoveToFrontEncode/filter <file> */
292 /* <target> <dict> MoveToFrontEncode/filter <file> */
293 private int
zMTFE(i_ctx_t * i_ctx_p)294 zMTFE(i_ctx_t *i_ctx_p)
295 {
296 os_ptr op = osp;
297
298 return filter_write_simple(op, &s_MTFE_template);
299 }
300
301 /* <source> MoveToFrontDecode/filter <file> */
302 /* <source> <dict> MoveToFrontDecode/filter <file> */
303 private int
zMTFD(i_ctx_t * i_ctx_p)304 zMTFD(i_ctx_t *i_ctx_p)
305 {
306 os_ptr op = osp;
307
308 return filter_read_simple(op, &s_MTFD_template);
309 }
310
311 /* ================ Initialization procedure ================ */
312
313 const op_def zfilterx_op_defs[] =
314 {
315 {"2.computecodes", zcomputecodes}, /* not a filter */
316 op_def_begin_filter(),
317 /* Non-standard filters */
318 {"2BoundedHuffmanEncode", zBHCE},
319 {"2BoundedHuffmanDecode", zBHCD},
320 {"2BWBlockSortEncode", zBWBSE},
321 {"2BWBlockSortDecode", zBWBSD},
322 {"2ByteTranslateEncode", zBTE},
323 {"2ByteTranslateDecode", zBTD},
324 {"1MoveToFrontEncode", zMTFE},
325 {"1MoveToFrontDecode", zMTFD},
326 op_def_end(0)
327 };
328