xref: /plan9/sys/src/cmd/gs/src/zfilter2.c (revision 593dc095aefb2a85c828727bbfa9da139a49bdf4)
1 /* Copyright (C) 1991, 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: zfilter2.c,v 1.6 2004/09/26 16:19:27 ray Exp $ */
18 /* Additional filter creation */
19 #include "memory_.h"
20 #include "ghost.h"
21 #include "oper.h"
22 #include "gsstruct.h"
23 #include "ialloc.h"
24 #include "idict.h"
25 #include "idparam.h"
26 #include "store.h"
27 #include "strimpl.h"
28 #include "sfilter.h"
29 #include "scfx.h"
30 #include "slzwx.h"
31 #include "spdiffx.h"
32 #include "spngpx.h"
33 #include "ifilter.h"
34 #include "ifilter2.h"
35 #include "ifwpred.h"
36 
37 /* ------ CCITTFaxEncode filter ------ */
38 
39 /* <target> <dict> CCITTFaxEncode/filter <file> */
40 private int
zCFE(i_ctx_t * i_ctx_p)41 zCFE(i_ctx_t *i_ctx_p)
42 {
43     os_ptr op = osp;
44     stream_CFE_state cfs;
45     int code;
46 
47     check_type(*op, t_dictionary);
48     check_dict_read(*op);
49     code = zcf_setup(op, (stream_CF_state *)&cfs, iimemory);
50     if (code < 0)
51 	return code;
52     return filter_write(i_ctx_p, 0, &s_CFE_template, (stream_state *)&cfs, 0);
53 }
54 
55 /* ------ Common setup for possibly pixel-oriented encoding filters ------ */
56 
57 int
filter_write_predictor(i_ctx_t * i_ctx_p,int npop,const stream_template * template,stream_state * st)58 filter_write_predictor(i_ctx_t *i_ctx_p, int npop,
59 		       const stream_template * template, stream_state * st)
60 {
61     os_ptr op = osp;
62     int predictor, code;
63     stream_PDiff_state pds;
64     stream_PNGP_state pps;
65 
66     if (r_has_type(op, t_dictionary)) {
67 	if ((code = dict_int_param(op, "Predictor", 0, 15, 1, &predictor)) < 0)
68 	    return code;
69 	switch (predictor) {
70 	    case 0:		/* identity */
71 		predictor = 1;
72 	    case 1:		/* identity */
73 		break;
74 	    case 2:		/* componentwise horizontal differencing */
75 		code = zpd_setup(op, &pds);
76 		break;
77 	    case 10:
78 	    case 11:
79 	    case 12:
80 	    case 13:
81 	    case 14:
82 	    case 15:
83 		/* PNG prediction */
84 		code = zpp_setup(op, &pps);
85 		break;
86 	    default:
87 		return_error(e_rangecheck);
88 	}
89 	if (code < 0)
90 	    return code;
91     } else
92 	predictor = 1;
93     if (predictor == 1)
94 	return filter_write(i_ctx_p, npop, template, st, 0);
95     {
96 	/* We need to cascade filters. */
97 	ref rtarget, rdict;
98 	int code;
99 
100 	/* Save the operands, just in case. */
101 	ref_assign(&rtarget, op - 1);
102 	ref_assign(&rdict, op);
103 	code = filter_write(i_ctx_p, npop, template, st, 0);
104 	if (code < 0)
105 	    return code;
106 	/* filter_write changed osp.... */
107 	op = osp;
108 	code =
109 	    (predictor == 2 ?
110 	     filter_write(i_ctx_p, 0, &s_PDiffE_template, (stream_state *)&pds, 0) :
111 	     filter_write(i_ctx_p, 0, &s_PNGPE_template, (stream_state *)&pps, 0));
112 	if (code < 0) {
113 	    /* Restore the operands.  Don't bother trying to clean up */
114 	    /* the first stream. */
115 	    osp = ++op;
116 	    ref_assign(op - 1, &rtarget);
117 	    ref_assign(op, &rdict);
118 	    return code;
119 	}
120 	/*
121 	 * Mark the compression stream as temporary, and propagate
122 	 * CloseTarget from it to the predictor stream.
123 	 */
124 	filter_mark_strm_temp(op, 2);
125 	return code;
126     }
127 }
128 
129 /* ------ LZW encoding filter ------ */
130 
131 /* <target> LZWEncode/filter <file> */
132 /* <target> <dict> LZWEncode/filter <file> */
133 private int
zLZWE(i_ctx_t * i_ctx_p)134 zLZWE(i_ctx_t *i_ctx_p)
135 {
136     os_ptr op = osp;
137     stream_LZW_state lzs;
138     int code = zlz_setup(op, &lzs);
139 
140     if (code < 0)
141 	return code;
142     return filter_write_predictor(i_ctx_p, 0, &s_LZWE_template,
143 				  (stream_state *) & lzs);
144 }
145 
146 /* ================ Initialization procedure ================ */
147 
148 const op_def zfilter2_op_defs[] =
149 {
150     op_def_begin_filter(),
151     {"2CCITTFaxEncode", zCFE},
152     {"1LZWEncode", zLZWE},
153     op_def_end(0)
154 };
155