1 /* Copyright (C) 1994, 2000 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: zfdecode.c,v 1.6 2004/03/13 22:31:19 ray Exp $ */
18 /* Additional decoding filter creation */
19 #include "memory_.h"
20 #include "ghost.h"
21 #include "oper.h"
22 #include "gsparam.h"
23 #include "gsstruct.h"
24 #include "ialloc.h"
25 #include "idict.h"
26 #include "idparam.h"
27 #include "ilevel.h" /* for LL3 test */
28 #include "iparam.h"
29 #include "store.h"
30 #include "stream.h" /* for setting is_temp */
31 #include "strimpl.h"
32 #include "sfilter.h"
33 #include "sa85x.h"
34 #include "scfx.h"
35 #include "scf.h"
36 #include "slzwx.h"
37 #include "spdiffx.h"
38 #include "spngpx.h"
39 #include "ifilter.h"
40 #include "ifilter2.h"
41 #include "ifrpred.h"
42
43 /* ------ ASCII85 filters ------ */
44
45 /* We include both encoding and decoding filters here, */
46 /* because it would be a nuisance to separate them. */
47
48 /* <target> ASCII85Encode/filter <file> */
49 /* <target> <dict> ASCII85Encode/filter <file> */
50 private int
zA85E(i_ctx_t * i_ctx_p)51 zA85E(i_ctx_t *i_ctx_p)
52 {
53 return filter_write_simple(i_ctx_p, &s_A85E_template);
54 }
55
56 /* <source> ASCII85Decode/filter <file> */
57 /* <source> <dict> ASCII85Decode/filter <file> */
58 private int
zA85D(i_ctx_t * i_ctx_p)59 zA85D(i_ctx_t *i_ctx_p)
60 {
61 return filter_read_simple(i_ctx_p, &s_A85D_template);
62 }
63
64 /* ------ CCITTFaxDecode filter ------ */
65
66 /* Common setup for encoding and decoding filters. */
67 extern stream_state_proc_put_params(s_CF_put_params, stream_CF_state);
68 int
zcf_setup(os_ptr op,stream_CF_state * pcfs,gs_ref_memory_t * imem)69 zcf_setup(os_ptr op, stream_CF_state *pcfs, gs_ref_memory_t *imem)
70 {
71 dict_param_list list;
72 int code = dict_param_list_read(&list, op, NULL, false, imem);
73
74 if (code < 0)
75 return code;
76 s_CF_set_defaults_inline(pcfs);
77 code = s_CF_put_params((gs_param_list *)&list, pcfs);
78 iparam_list_release(&list);
79 return code;
80 }
81
82 /* <source> <dict> CCITTFaxDecode/filter <file> */
83 /* <source> CCITTFaxDecode/filter <file> */
84 private int
zCFD(i_ctx_t * i_ctx_p)85 zCFD(i_ctx_t *i_ctx_p)
86 {
87 os_ptr op = osp;
88 os_ptr dop;
89 stream_CFD_state cfs;
90 int code;
91
92 if (r_has_type(op, t_dictionary)) {
93 check_dict_read(*op);
94 dop = op;
95 } else
96 dop = 0;
97 code = zcf_setup(dop, (stream_CF_state *)&cfs, iimemory);
98 if (code < 0)
99 return code;
100 return filter_read(i_ctx_p, 0, &s_CFD_template, (stream_state *)&cfs, 0);
101 }
102
103 /* ------ Common setup for possibly pixel-oriented decoding filters ------ */
104
105 int
filter_read_predictor(i_ctx_t * i_ctx_p,int npop,const stream_template * template,stream_state * st)106 filter_read_predictor(i_ctx_t *i_ctx_p, int npop,
107 const stream_template * template, stream_state * st)
108 {
109 os_ptr op = osp;
110 int predictor, code;
111 stream_PDiff_state pds;
112 stream_PNGP_state pps;
113
114 if (r_has_type(op, t_dictionary)) {
115 if ((code = dict_int_param(op, "Predictor", 0, 15, 1, &predictor)) < 0)
116 return code;
117 switch (predictor) {
118 case 0: /* identity */
119 predictor = 1;
120 case 1: /* identity */
121 break;
122 case 2: /* componentwise horizontal differencing */
123 code = zpd_setup(op, &pds);
124 break;
125 case 10:
126 case 11:
127 case 12:
128 case 13:
129 case 14:
130 case 15:
131 /* PNG prediction */
132 code = zpp_setup(op, &pps);
133 break;
134 default:
135 return_error(e_rangecheck);
136 }
137 if (code < 0)
138 return code;
139 } else
140 predictor = 1;
141 if (predictor == 1)
142 return filter_read(i_ctx_p, npop, template, st, 0);
143 {
144 /* We need to cascade filters. */
145 ref rsource, rdict;
146 int code;
147
148 /* Save the operands, just in case. */
149 ref_assign(&rsource, op - 1);
150 ref_assign(&rdict, op);
151 code = filter_read(i_ctx_p, 1, template, st, 0);
152 if (code < 0)
153 return code;
154 /* filter_read changed osp.... */
155 op = osp;
156 code =
157 (predictor == 2 ?
158 filter_read(i_ctx_p, 0, &s_PDiffD_template, (stream_state *) & pds, 0) :
159 filter_read(i_ctx_p, 0, &s_PNGPD_template, (stream_state *) & pps, 0));
160 if (code < 0) {
161 /* Restore the operands. Don't bother trying to clean up */
162 /* the first stream. */
163 osp = ++op;
164 ref_assign(op - 1, &rsource);
165 ref_assign(op, &rdict);
166 return code;
167 }
168 /*
169 * Mark the compression stream as temporary, and propagate
170 * CloseSource from it to the predictor stream.
171 */
172 filter_mark_strm_temp(op, 2);
173 return code;
174 }
175 }
176
177 /* ------ Generalized LZW/GIF decoding filter ------ */
178
179 /* Common setup for encoding and decoding filters. */
180 int
zlz_setup(os_ptr op,stream_LZW_state * plzs)181 zlz_setup(os_ptr op, stream_LZW_state * plzs)
182 {
183 int code;
184 const ref *dop;
185
186 if (r_has_type(op, t_dictionary)) {
187 check_dict_read(*op);
188 dop = op;
189 } else
190 dop = 0;
191 if ( (code = dict_int_param(dop, "EarlyChange", 0, 1, 1,
192 &plzs->EarlyChange)) < 0 ||
193 /*
194 * The following are not PostScript standard, although
195 * LanguageLevel 3 provides the first two under different
196 * names.
197 */
198 (code = dict_int_param(dop, "InitialCodeLength", 2, 11, 8,
199 &plzs->InitialCodeLength)) < 0 ||
200 (code = dict_bool_param(dop, "FirstBitLowOrder", false,
201 &plzs->FirstBitLowOrder)) < 0 ||
202 (code = dict_bool_param(dop, "BlockData", false,
203 &plzs->BlockData)) < 0
204 )
205 return code;
206 return 0;
207 }
208
209 /* <source> LZWDecode/filter <file> */
210 /* <source> <dict> LZWDecode/filter <file> */
211 private int
zLZWD(i_ctx_t * i_ctx_p)212 zLZWD(i_ctx_t *i_ctx_p)
213 {
214 os_ptr op = osp;
215 stream_LZW_state lzs;
216 int code = zlz_setup(op, &lzs);
217
218 if (code < 0)
219 return code;
220 if (LL3_ENABLED && r_has_type(op, t_dictionary)) {
221 int unit_size;
222
223 if ((code = dict_bool_param(op, "LowBitFirst", lzs.FirstBitLowOrder,
224 &lzs.FirstBitLowOrder)) < 0 ||
225 (code = dict_int_param(op, "UnitSize", 3, 8, 8,
226 &unit_size)) < 0
227 )
228 return code;
229 if (code == 0 /* UnitSize specified */ )
230 lzs.InitialCodeLength = unit_size + 1;
231 }
232 return filter_read_predictor(i_ctx_p, 0, &s_LZWD_template,
233 (stream_state *) & lzs);
234 }
235
236 /* ------ Color differencing filters ------ */
237
238 /* We include both encoding and decoding filters here, */
239 /* because it would be a nuisance to separate them. */
240
241 /* Common setup for encoding and decoding filters. */
242 int
zpd_setup(os_ptr op,stream_PDiff_state * ppds)243 zpd_setup(os_ptr op, stream_PDiff_state * ppds)
244 {
245 int code, bpc;
246
247 check_type(*op, t_dictionary);
248 check_dict_read(*op);
249 if ((code = dict_int_param(op, "Colors", 1, s_PDiff_max_Colors, 1,
250 &ppds->Colors)) < 0 ||
251 (code = dict_int_param(op, "BitsPerComponent", 1, 16, 8,
252 &bpc)) < 0 ||
253 (bpc & (bpc - 1)) != 0 ||
254 (code = dict_int_param(op, "Columns", 1, max_int, 1,
255 &ppds->Columns)) < 0
256 )
257 return (code < 0 ? code : gs_note_error(e_rangecheck));
258 ppds->BitsPerComponent = bpc;
259 return 0;
260 }
261
262 /* <target> <dict> PixelDifferenceEncode/filter <file> */
263 private int
zPDiffE(i_ctx_t * i_ctx_p)264 zPDiffE(i_ctx_t *i_ctx_p)
265 {
266 os_ptr op = osp;
267 stream_PDiff_state pds;
268 int code = zpd_setup(op, &pds);
269
270 if (code < 0)
271 return code;
272 return filter_write(i_ctx_p, 0, &s_PDiffE_template, (stream_state *) & pds, 0);
273 }
274
275 /* <source> <dict> PixelDifferenceDecode/filter <file> */
276 private int
zPDiffD(i_ctx_t * i_ctx_p)277 zPDiffD(i_ctx_t *i_ctx_p)
278 {
279 os_ptr op = osp;
280 stream_PDiff_state pds;
281 int code = zpd_setup(op, &pds);
282
283 if (code < 0)
284 return code;
285 return filter_read(i_ctx_p, 0, &s_PDiffD_template, (stream_state *) & pds, 0);
286 }
287
288 /* ------ PNG pixel predictor filters ------ */
289
290 /* Common setup for encoding and decoding filters. */
291 int
zpp_setup(os_ptr op,stream_PNGP_state * ppps)292 zpp_setup(os_ptr op, stream_PNGP_state * ppps)
293 {
294 int code, bpc;
295
296 check_type(*op, t_dictionary);
297 check_dict_read(*op);
298 if ((code = dict_int_param(op, "Colors", 1, 16, 1,
299 &ppps->Colors)) < 0 ||
300 (code = dict_int_param(op, "BitsPerComponent", 1, 16, 8,
301 &bpc)) < 0 ||
302 (bpc & (bpc - 1)) != 0 ||
303 (code = dict_uint_param(op, "Columns", 1, max_uint, 1,
304 &ppps->Columns)) < 0 ||
305 (code = dict_int_param(op, "Predictor", 10, 15, 15,
306 &ppps->Predictor)) < 0
307 )
308 return (code < 0 ? code : gs_note_error(e_rangecheck));
309 ppps->BitsPerComponent = bpc;
310 return 0;
311 }
312
313 /* <target> <dict> PNGPredictorEncode/filter <file> */
314 private int
zPNGPE(i_ctx_t * i_ctx_p)315 zPNGPE(i_ctx_t *i_ctx_p)
316 {
317 os_ptr op = osp;
318 stream_PNGP_state pps;
319 int code = zpp_setup(op, &pps);
320
321 if (code < 0)
322 return code;
323 return filter_write(i_ctx_p, 0, &s_PNGPE_template, (stream_state *) & pps, 0);
324 }
325
326 /* <source> <dict> PNGPredictorDecode/filter <file> */
327 private int
zPNGPD(i_ctx_t * i_ctx_p)328 zPNGPD(i_ctx_t *i_ctx_p)
329 {
330 os_ptr op = osp;
331 stream_PNGP_state pps;
332 int code = zpp_setup(op, &pps);
333
334 if (code < 0)
335 return code;
336 return filter_read(i_ctx_p, 0, &s_PNGPD_template, (stream_state *) & pps, 0);
337 }
338
339 /* ---------------- Initialization procedure ---------------- */
340
341 const op_def zfdecode_op_defs[] = {
342 op_def_begin_filter(),
343 {"1ASCII85Encode", zA85E},
344 {"1ASCII85Decode", zA85D},
345 {"2CCITTFaxDecode", zCFD},
346 {"1LZWDecode", zLZWD},
347 {"2PixelDifferenceDecode", zPDiffD},
348 {"2PixelDifferenceEncode", zPDiffE},
349 {"2PNGPredictorDecode", zPNGPD},
350 {"2PNGPredictorEncode", zPNGPE},
351 op_def_end(0)
352 };
353