/* Copyright (C) 1994, 2000 artofcode LLC. All rights reserved. This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA, 02111-1307. */ /*$Id: zfdecode.c,v 1.3.6.1.2.1 2003/01/17 00:49:06 giles Exp $ */ /* Additional decoding filter creation */ #include "memory_.h" #include "ghost.h" #include "oper.h" #include "gsparam.h" #include "gsstruct.h" #include "ialloc.h" #include "idict.h" #include "idparam.h" #include "ilevel.h" /* for LL3 test */ #include "iparam.h" #include "store.h" #include "stream.h" /* for setting is_temp */ #include "strimpl.h" #include "sfilter.h" #include "sa85x.h" #include "scfx.h" #include "scf.h" #include "slzwx.h" #include "spdiffx.h" #include "spngpx.h" #include "ifilter.h" #include "ifilter2.h" #include "ifrpred.h" /* ------ ASCII85 filters ------ */ /* We include both encoding and decoding filters here, */ /* because it would be a nuisance to separate them. */ /* ASCII85Encode/filter */ /* ASCII85Encode/filter */ private int zA85E(i_ctx_t *i_ctx_p) { return filter_write_simple(i_ctx_p, &s_A85E_template); } /* ASCII85Decode/filter */ /* ASCII85Decode/filter */ private int zA85D(i_ctx_t *i_ctx_p) { return filter_read_simple(i_ctx_p, &s_A85D_template); } /* ------ CCITTFaxDecode filter ------ */ /* Common setup for encoding and decoding filters. */ extern stream_state_proc_put_params(s_CF_put_params, stream_CF_state); int zcf_setup(os_ptr op, stream_CF_state *pcfs, gs_ref_memory_t *imem) { dict_param_list list; int code = dict_param_list_read(&list, op, NULL, false, imem); if (code < 0) return code; s_CF_set_defaults_inline(pcfs); code = s_CF_put_params((gs_param_list *)&list, pcfs); iparam_list_release(&list); return code; } /* CCITTFaxDecode/filter */ /* CCITTFaxDecode/filter */ private int zCFD(i_ctx_t *i_ctx_p) { os_ptr op = osp; os_ptr dop; stream_CFD_state cfs; int code; if (r_has_type(op, t_dictionary)) { check_dict_read(*op); dop = op; } else dop = 0; code = zcf_setup(dop, (stream_CF_state *)&cfs, iimemory); if (code < 0) return code; return filter_read(i_ctx_p, 0, &s_CFD_template, (stream_state *)&cfs, 0); } /* ------ Common setup for possibly pixel-oriented decoding filters ------ */ int filter_read_predictor(i_ctx_t *i_ctx_p, int npop, const stream_template * template, stream_state * st) { os_ptr op = osp; int predictor, code; stream_PDiff_state pds; stream_PNGP_state pps; if (r_has_type(op, t_dictionary)) { if ((code = dict_int_param(op, "Predictor", 0, 15, 1, &predictor)) < 0) return code; switch (predictor) { case 0: /* identity */ predictor = 1; case 1: /* identity */ break; case 2: /* componentwise horizontal differencing */ code = zpd_setup(op, &pds); break; case 10: case 11: case 12: case 13: case 14: case 15: /* PNG prediction */ code = zpp_setup(op, &pps); break; default: return_error(e_rangecheck); } if (code < 0) return code; } else predictor = 1; if (predictor == 1) return filter_read(i_ctx_p, npop, template, st, 0); { /* We need to cascade filters. */ ref rsource, rdict; int code; /* Save the operands, just in case. */ ref_assign(&rsource, op - 1); ref_assign(&rdict, op); code = filter_read(i_ctx_p, 1, template, st, 0); if (code < 0) return code; /* filter_read changed osp.... */ op = osp; code = (predictor == 2 ? filter_read(i_ctx_p, 0, &s_PDiffD_template, (stream_state *) & pds, 0) : filter_read(i_ctx_p, 0, &s_PNGPD_template, (stream_state *) & pps, 0)); if (code < 0) { /* Restore the operands. Don't bother trying to clean up */ /* the first stream. */ osp = ++op; ref_assign(op - 1, &rsource); ref_assign(op, &rdict); return code; } /* * Mark the compression stream as temporary, and propagate * CloseSource from it to the predictor stream. */ filter_mark_strm_temp(op, 2); return code; } } /* ------ Generalized LZW/GIF decoding filter ------ */ /* Common setup for encoding and decoding filters. */ int zlz_setup(os_ptr op, stream_LZW_state * plzs) { int code; const ref *dop; if (r_has_type(op, t_dictionary)) { check_dict_read(*op); dop = op; } else dop = 0; if ( (code = dict_int_param(dop, "EarlyChange", 0, 1, 1, &plzs->EarlyChange)) < 0 || /* * The following are not PostScript standard, although * LanguageLevel 3 provides the first two under different * names. */ (code = dict_int_param(dop, "InitialCodeLength", 2, 11, 8, &plzs->InitialCodeLength)) < 0 || (code = dict_bool_param(dop, "FirstBitLowOrder", false, &plzs->FirstBitLowOrder)) < 0 || (code = dict_bool_param(dop, "BlockData", false, &plzs->BlockData)) < 0 ) return code; return 0; } /* LZWDecode/filter */ /* LZWDecode/filter */ private int zLZWD(i_ctx_t *i_ctx_p) { os_ptr op = osp; stream_LZW_state lzs; int code = zlz_setup(op, &lzs); if (code < 0) return code; if (LL3_ENABLED && r_has_type(op, t_dictionary)) { int unit_size; if ((code = dict_bool_param(op, "LowBitFirst", lzs.FirstBitLowOrder, &lzs.FirstBitLowOrder)) < 0 || (code = dict_int_param(op, "UnitSize", 3, 8, 8, &unit_size)) < 0 ) return code; if (code == 0 /* UnitSize specified */ ) lzs.InitialCodeLength = unit_size + 1; } return filter_read_predictor(i_ctx_p, 0, &s_LZWD_template, (stream_state *) & lzs); } /* ------ Color differencing filters ------ */ /* We include both encoding and decoding filters here, */ /* because it would be a nuisance to separate them. */ /* Common setup for encoding and decoding filters. */ int zpd_setup(os_ptr op, stream_PDiff_state * ppds) { int code, bpc; check_type(*op, t_dictionary); check_dict_read(*op); if ((code = dict_int_param(op, "Colors", 1, s_PDiff_max_Colors, 1, &ppds->Colors)) < 0 || (code = dict_int_param(op, "BitsPerComponent", 1, 8, 8, &bpc)) < 0 || (bpc & (bpc - 1)) != 0 || (code = dict_int_param(op, "Columns", 1, max_int, 1, &ppds->Columns)) < 0 ) return (code < 0 ? code : gs_note_error(e_rangecheck)); ppds->BitsPerComponent = bpc; return 0; } /* PixelDifferenceEncode/filter */ private int zPDiffE(i_ctx_t *i_ctx_p) { os_ptr op = osp; stream_PDiff_state pds; int code = zpd_setup(op, &pds); if (code < 0) return code; return filter_write(i_ctx_p, 0, &s_PDiffE_template, (stream_state *) & pds, 0); } /* PixelDifferenceDecode/filter */ private int zPDiffD(i_ctx_t *i_ctx_p) { os_ptr op = osp; stream_PDiff_state pds; int code = zpd_setup(op, &pds); if (code < 0) return code; return filter_read(i_ctx_p, 0, &s_PDiffD_template, (stream_state *) & pds, 0); } /* ------ PNG pixel predictor filters ------ */ /* Common setup for encoding and decoding filters. */ int zpp_setup(os_ptr op, stream_PNGP_state * ppps) { int code, bpc; check_type(*op, t_dictionary); check_dict_read(*op); if ((code = dict_int_param(op, "Colors", 1, 16, 1, &ppps->Colors)) < 0 || (code = dict_int_param(op, "BitsPerComponent", 1, 16, 8, &bpc)) < 0 || (bpc & (bpc - 1)) != 0 || (code = dict_uint_param(op, "Columns", 1, max_uint, 1, &ppps->Columns)) < 0 || (code = dict_int_param(op, "Predictor", 10, 15, 15, &ppps->Predictor)) < 0 ) return (code < 0 ? code : gs_note_error(e_rangecheck)); ppps->BitsPerComponent = bpc; return 0; } /* PNGPredictorEncode/filter */ private int zPNGPE(i_ctx_t *i_ctx_p) { os_ptr op = osp; stream_PNGP_state pps; int code = zpp_setup(op, &pps); if (code < 0) return code; return filter_write(i_ctx_p, 0, &s_PNGPE_template, (stream_state *) & pps, 0); } /* PNGPredictorDecode/filter */ private int zPNGPD(i_ctx_t *i_ctx_p) { os_ptr op = osp; stream_PNGP_state pps; int code = zpp_setup(op, &pps); if (code < 0) return code; return filter_read(i_ctx_p, 0, &s_PNGPD_template, (stream_state *) & pps, 0); } /* ---------------- Initialization procedure ---------------- */ const op_def zfdecode_op_defs[] = { op_def_begin_filter(), {"1ASCII85Encode", zA85E}, {"1ASCII85Decode", zA85D}, {"2CCITTFaxDecode", zCFD}, {"1LZWDecode", zLZWD}, {"2PixelDifferenceDecode", zPDiffD}, {"2PixelDifferenceEncode", zPDiffE}, {"2PNGPredictorDecode", zPNGPD}, {"2PNGPredictorEncode", zPNGPE}, op_def_end(0) };