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 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 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 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 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 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 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 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 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 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 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 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 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 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