/src/ghostpdl/psi/zfdecode.c
Line | Count | Source (jump to first uncovered line) |
1 | | /* Copyright (C) 2001-2025 Artifex Software, Inc. |
2 | | All Rights Reserved. |
3 | | |
4 | | This software is provided AS-IS with no warranty, either express or |
5 | | implied. |
6 | | |
7 | | This software is distributed under license and may not be copied, |
8 | | modified or distributed except as expressly authorized under the terms |
9 | | of the license contained in the file LICENSE in this distribution. |
10 | | |
11 | | Refer to licensing information at http://www.artifex.com or contact |
12 | | Artifex Software, Inc., 39 Mesa Street, Suite 108A, San Francisco, |
13 | | CA 94129, USA, for further information. |
14 | | */ |
15 | | |
16 | | |
17 | | /* Additional decoding filter creation */ |
18 | | #include "memory_.h" |
19 | | #include "ghost.h" |
20 | | #include "oper.h" |
21 | | #include "gsparam.h" |
22 | | #include "gsstruct.h" |
23 | | #include "ialloc.h" |
24 | | #include "idict.h" |
25 | | #include "idparam.h" |
26 | | #include "ilevel.h" /* for LL3 test */ |
27 | | #include "iparam.h" |
28 | | #include "store.h" |
29 | | #include "stream.h" /* for setting is_temp */ |
30 | | #include "strimpl.h" |
31 | | #include "sfilter.h" |
32 | | #include "sa85x.h" |
33 | | #include "scfx.h" |
34 | | #include "scf.h" |
35 | | #include "slzwx.h" |
36 | | #include "spdiffx.h" |
37 | | #include "spngpx.h" |
38 | | #include "ifilter.h" |
39 | | #include "ifilter2.h" |
40 | | #include "ifrpred.h" |
41 | | |
42 | | /* ------ ASCII85 filters ------ */ |
43 | | |
44 | | /* We include both encoding and decoding filters here, */ |
45 | | /* because it would be a nuisance to separate them. */ |
46 | | |
47 | | /* <target> ASCII85Encode/filter <file> */ |
48 | | /* <target> <dict> ASCII85Encode/filter <file> */ |
49 | | static int |
50 | | zA85E(i_ctx_t *i_ctx_p) |
51 | 0 | { |
52 | 0 | return filter_write_simple(i_ctx_p, &s_A85E_template); |
53 | 0 | } |
54 | | |
55 | | /* <source> ASCII85Decode/filter <file> */ |
56 | | /* <source> <dict> ASCII85Decode/filter <file> */ |
57 | | static int |
58 | | zA85D(i_ctx_t *i_ctx_p) |
59 | 1 | { |
60 | 1 | os_ptr op = osp; |
61 | 1 | stream_A85D_state ss; |
62 | 1 | int code; |
63 | | |
64 | 1 | if (r_has_type(op, t_dictionary)) { |
65 | 0 | check_dict_read(*op); |
66 | 0 | if ((code = dict_bool_param(op, "PDFRules", false, &ss.pdf_rules)) < 0) |
67 | 0 | return code; |
68 | 1 | } else { |
69 | 1 | ss.pdf_rules = false; |
70 | 1 | } |
71 | 1 | return filter_read(i_ctx_p, 0, &s_A85D_template, (stream_state *)&ss, 0); |
72 | 1 | } |
73 | | |
74 | | /* ------ CCITTFaxDecode filter ------ */ |
75 | | |
76 | | /* Common setup for encoding and decoding filters. */ |
77 | | extern stream_state_proc_put_params(s_CF_put_params, stream_CF_state); |
78 | | int |
79 | | zcf_setup(os_ptr op, stream_CF_state *pcfs, gs_ref_memory_t *imem) |
80 | 0 | { |
81 | 0 | dict_param_list list; |
82 | 0 | int code = dict_param_list_read(&list, op, NULL, false, imem); |
83 | |
|
84 | 0 | if (code < 0) |
85 | 0 | return code; |
86 | 0 | s_CF_set_defaults_inline(pcfs); |
87 | 0 | code = s_CF_put_params((gs_param_list *)&list, pcfs); |
88 | 0 | iparam_list_release(&list); |
89 | 0 | return code; |
90 | 0 | } |
91 | | |
92 | | /* <source> <dict> CCITTFaxDecode/filter <file> */ |
93 | | /* <source> CCITTFaxDecode/filter <file> */ |
94 | | static int |
95 | | zCFD(i_ctx_t *i_ctx_p) |
96 | 0 | { |
97 | 0 | os_ptr op = osp; |
98 | 0 | os_ptr dop; |
99 | 0 | stream_CFD_state cfs; |
100 | 0 | int code; |
101 | |
|
102 | 0 | if (r_has_type(op, t_dictionary)) { |
103 | 0 | check_dict_read(*op); |
104 | 0 | dop = op; |
105 | 0 | } else |
106 | 0 | dop = 0; |
107 | 0 | code = zcf_setup(dop, (stream_CF_state *)&cfs, iimemory); |
108 | 0 | if (code < 0) |
109 | 0 | return code; |
110 | 0 | return filter_read(i_ctx_p, 0, &s_CFD_template, (stream_state *)&cfs, 0); |
111 | 0 | } |
112 | | |
113 | | /* ------ Common setup for possibly pixel-oriented decoding filters ------ */ |
114 | | |
115 | | int |
116 | | filter_read_predictor(i_ctx_t *i_ctx_p, int npop, |
117 | | const stream_template * templat, stream_state * st) |
118 | 1 | { |
119 | 1 | os_ptr op = osp; |
120 | 1 | int predictor, code; |
121 | 1 | stream_PDiff_state pds; |
122 | 1 | stream_PNGP_state pps; |
123 | | |
124 | 1 | if (r_has_type(op, t_dictionary)) { |
125 | 0 | if ((code = dict_int_param(op, "Predictor", 0, 15, 1, &predictor)) < 0) |
126 | 0 | return code; |
127 | 0 | switch (predictor) { |
128 | 0 | case 0: /* identity */ |
129 | 0 | predictor = 1; |
130 | 0 | case 1: /* identity */ |
131 | 0 | break; |
132 | 0 | case 2: /* componentwise horizontal differencing */ |
133 | 0 | code = zpd_setup(op, &pds); |
134 | 0 | break; |
135 | 0 | case 10: |
136 | 0 | case 11: |
137 | 0 | case 12: |
138 | 0 | case 13: |
139 | 0 | case 14: |
140 | 0 | case 15: |
141 | | /* PNG prediction */ |
142 | 0 | code = zpp_setup(op, &pps); |
143 | 0 | break; |
144 | 0 | default: |
145 | 0 | return_error(gs_error_rangecheck); |
146 | 0 | } |
147 | 0 | if (code < 0) |
148 | 0 | return code; |
149 | 0 | } else |
150 | 1 | predictor = 1; |
151 | 1 | if (predictor == 1) |
152 | 1 | return filter_read(i_ctx_p, npop, templat, st, 0); |
153 | 0 | { |
154 | | /* We need to cascade filters. */ |
155 | 0 | ref rsource, rdict; |
156 | 0 | int code; |
157 | | |
158 | | /* Save the operands, just in case. */ |
159 | 0 | ref_assign(&rsource, op - 1); |
160 | 0 | ref_assign(&rdict, op); |
161 | 0 | code = filter_read(i_ctx_p, 1, templat, st, 0); |
162 | 0 | if (code < 0) |
163 | 0 | return code; |
164 | | /* filter_read changed osp.... */ |
165 | 0 | op = osp; |
166 | 0 | code = |
167 | 0 | (predictor == 2 ? |
168 | 0 | filter_read(i_ctx_p, 0, &s_PDiffD_template, (stream_state *) & pds, 0) : |
169 | 0 | filter_read(i_ctx_p, 0, &s_PNGPD_template, (stream_state *) & pps, 0)); |
170 | 0 | if (code < 0) { |
171 | | /* Restore the operands. Don't bother trying to clean up */ |
172 | | /* the first stream. */ |
173 | 0 | osp = ++op; |
174 | 0 | ref_assign(op - 1, &rsource); |
175 | 0 | ref_assign(op, &rdict); |
176 | 0 | return code; |
177 | 0 | } |
178 | | /* |
179 | | * Mark the compression stream as temporary, and propagate |
180 | | * CloseSource from it to the predictor stream. |
181 | | */ |
182 | 0 | filter_mark_strm_temp(op, 2); |
183 | 0 | return code; |
184 | 0 | } |
185 | 0 | } |
186 | | |
187 | | /* ------ Generalized LZW/GIF decoding filter ------ */ |
188 | | |
189 | | /* Common setup for encoding and decoding filters. */ |
190 | | int |
191 | | zlz_setup(os_ptr op, stream_LZW_state * plzs) |
192 | 1 | { |
193 | 1 | int code, ech; |
194 | 1 | const ref *dop; |
195 | | |
196 | 1 | s_LZW_set_defaults_inline(plzs); |
197 | 1 | if (r_has_type(op, t_dictionary)) { |
198 | 0 | check_dict_read(*op); |
199 | 0 | dop = op; |
200 | 0 | } else |
201 | 1 | dop = 0; |
202 | 1 | if ( (code = dict_int_param(dop, "EarlyChange", 0, 1, 1, |
203 | 1 | &ech)) < 0 || |
204 | | /* |
205 | | * The following are not PostScript standard, although |
206 | | * LanguageLevel 3 provides the first two under different |
207 | | * names. |
208 | | */ |
209 | 1 | (code = dict_int_param(dop, "InitialCodeLength", 2, 11, 8, |
210 | 1 | &plzs->InitialCodeLength)) < 0 || |
211 | 1 | (code = dict_bool_param(dop, "FirstBitLowOrder", false, |
212 | 1 | &plzs->FirstBitLowOrder)) < 0 || |
213 | 1 | (code = dict_bool_param(dop, "BlockData", false, |
214 | 1 | &plzs->BlockData)) < 0 |
215 | 1 | ) |
216 | 0 | return code; |
217 | 1 | plzs->EarlyChange = ech != 0; |
218 | 1 | return 0; |
219 | 1 | } |
220 | | |
221 | | /* <source> LZWDecode/filter <file> */ |
222 | | /* <source> <dict> LZWDecode/filter <file> */ |
223 | | static int |
224 | | zLZWD(i_ctx_t *i_ctx_p) |
225 | 1 | { |
226 | 1 | os_ptr op = osp; |
227 | 1 | stream_LZW_state lzs; |
228 | 1 | int code = zlz_setup(op, &lzs); |
229 | | |
230 | 1 | if (code < 0) |
231 | 0 | return code; |
232 | 1 | if (LL3_ENABLED && r_has_type(op, t_dictionary)) { |
233 | 0 | int unit_size; |
234 | |
|
235 | 0 | if ((code = dict_bool_param(op, "LowBitFirst", lzs.FirstBitLowOrder, |
236 | 0 | &lzs.FirstBitLowOrder)) < 0 || |
237 | 0 | (code = dict_int_param(op, "UnitSize", 3, 8, 8, |
238 | 0 | &unit_size)) < 0 |
239 | 0 | ) |
240 | 0 | return code; |
241 | 0 | if (code == 0 /* UnitSize specified */ ) |
242 | 0 | lzs.InitialCodeLength = unit_size + 1; |
243 | 0 | } |
244 | 1 | return filter_read_predictor(i_ctx_p, 0, &s_LZWD_template, |
245 | 1 | (stream_state *) & lzs); |
246 | 1 | } |
247 | | |
248 | | /* ------ Color differencing filters ------ */ |
249 | | |
250 | | /* We include both encoding and decoding filters here, */ |
251 | | /* because it would be a nuisance to separate them. */ |
252 | | |
253 | | /* Common setup for encoding and decoding filters. */ |
254 | | int |
255 | | zpd_setup(os_ptr op, stream_PDiff_state * ppds) |
256 | 0 | { |
257 | 0 | int code, bpc; |
258 | |
|
259 | 0 | check_type(*op, t_dictionary); |
260 | 0 | check_dict_read(*op); |
261 | 0 | if ((code = dict_int_param(op, "Colors", 1, s_PDiff_max_Colors, 1, |
262 | 0 | &ppds->Colors)) < 0 || |
263 | 0 | (code = dict_int_param(op, "BitsPerComponent", 1, 16, 8, |
264 | 0 | &bpc)) < 0 || |
265 | 0 | (bpc & (bpc - 1)) != 0 || |
266 | 0 | (code = dict_int_param(op, "Columns", 1, max_int, 1, |
267 | 0 | &ppds->Columns)) < 0 |
268 | 0 | ) |
269 | 0 | return (code < 0 ? code : gs_note_error(gs_error_rangecheck)); |
270 | 0 | ppds->BitsPerComponent = bpc; |
271 | 0 | return 0; |
272 | 0 | } |
273 | | |
274 | | /* ------ PNG pixel predictor filters ------ */ |
275 | | |
276 | | /* Common setup for encoding and decoding filters. */ |
277 | | int |
278 | | zpp_setup(os_ptr op, stream_PNGP_state * ppps) |
279 | 0 | { |
280 | 0 | int code, bpc; |
281 | |
|
282 | 0 | check_type(*op, t_dictionary); |
283 | 0 | check_dict_read(*op); |
284 | 0 | if ((code = dict_int_param(op, "Colors", 1, s_PNG_max_Colors, 1, |
285 | 0 | &ppps->Colors)) < 0 || |
286 | 0 | (code = dict_int_param(op, "BitsPerComponent", 1, 16, 8, |
287 | 0 | &bpc)) < 0 || |
288 | 0 | (bpc & (bpc - 1)) != 0 || |
289 | 0 | (code = dict_uint_param(op, "Columns", 1, max_uint, 1, |
290 | 0 | &ppps->Columns)) < 0 || |
291 | 0 | (code = dict_int_param(op, "Predictor", 10, 15, 15, |
292 | 0 | &ppps->Predictor)) < 0 |
293 | 0 | ) |
294 | 0 | return (code < 0 ? code : gs_note_error(gs_error_rangecheck)); |
295 | 0 | ppps->BitsPerComponent = bpc; |
296 | 0 | return 0; |
297 | 0 | } |
298 | | |
299 | | /* ---------------- Initialization procedure ---------------- */ |
300 | | |
301 | | const op_def zfdecode_op_defs[] = { |
302 | | op_def_begin_filter(), |
303 | | {"1ASCII85Encode", zA85E}, |
304 | | {"1ASCII85Decode", zA85D}, |
305 | | {"2CCITTFaxDecode", zCFD}, |
306 | | {"1LZWDecode", zLZWD}, |
307 | | op_def_end(0) |
308 | | }; |