xref: /plan9/sys/src/cmd/gs/src/zfdecode.c (revision 593dc095aefb2a85c828727bbfa9da139a49bdf4)
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