1 /* Copyright (C) 2003 artofcode LLC. 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: sjbig2.c,v 1.7 2005/06/09 07:15:07 giles Exp $ */
18 /* jbig2decode filter implementation -- hooks in libjbig2dec */
19
20 #include "stdint_.h"
21 #include "memory_.h"
22 #include "stdio_.h" /* sprintf() for debug output */
23
24 #include "gserrors.h"
25 #include "gserror.h"
26 #include "gdebug.h"
27 #include "strimpl.h"
28 #include "sjbig2.h"
29
30 /* stream implementation */
31
32 /* The /JBIG2Decode filter is a fairly memory intensive one to begin with,
33 particularly in the initial jbig2dec library implementation. Furthermore,
34 as a PDF 1.4 feature, we can assume a fairly large (host-level) machine.
35 We therefore dispense with the normal Ghostscript memory discipline and
36 let the library allocate all its resources on the heap. The pointers to
37 these are not enumerated and so will not be garbage collected. We rely
38 on our release() proc being called to deallocate state.
39 */
40
41 private_st_jbig2decode_state(); /* creates a gc object for our state, defined in sjbig2.h */
42
43 /* error callback for jbig2 decoder */
44 private int
s_jbig2decode_error(void * error_callback_data,const char * msg,Jbig2Severity severity,int32_t seg_idx)45 s_jbig2decode_error(void *error_callback_data, const char *msg, Jbig2Severity severity,
46 int32_t seg_idx)
47 {
48 stream_jbig2decode_state *const state =
49 (stream_jbig2decode_state *) error_callback_data;
50 const char *type;
51 char segment[22];
52 int code = 0;
53
54 switch (severity) {
55 #ifdef JBIG2_DEBUG /* verbose reporting when debugging */
56 case JBIG2_SEVERITY_DEBUG:
57 type = "DEBUG"; break;;
58 case JBIG2_SEVERITY_INFO:
59 type = "info"; break;;
60 case JBIG2_SEVERITY_WARNING:
61 type = "WARNING"; break;;
62 #else /* suppress most messages in normal operation */
63 case JBIG2_SEVERITY_DEBUG:
64 case JBIG2_SEVERITY_INFO:
65 case JBIG2_SEVERITY_WARNING:
66 return 0;
67 break;;
68 #endif /* JBIG2_DEBUG */
69 case JBIG2_SEVERITY_FATAL:
70 type = "FATAL ERROR decoding image:";
71 /* pass the fatal error upstream if possible */
72 code = gs_error_ioerror;
73 if (state != NULL) state->error = code;
74 break;;
75 default: type = "unknown message:"; break;;
76 }
77 if (seg_idx == -1) segment[0] = '\0';
78 else sprintf(segment, "(segment 0x%02x)", seg_idx);
79
80 dlprintf3("jbig2dec %s %s %s\n", type, msg, segment);
81
82 return code;
83 }
84
85 /* invert the bits in a buffer */
86 /* jbig2 and postscript have different senses of what pixel
87 value is black, so we must invert the image */
88 private void
s_jbig2decode_invert_buffer(unsigned char * buf,int length)89 s_jbig2decode_invert_buffer(unsigned char *buf, int length)
90 {
91 int i;
92
93 for (i = 0; i < length; i++)
94 *buf++ ^= 0xFF;
95 }
96
97 /* parse a globals stream packed into a gs_bytestring for us by the postscript
98 layer and stuff the resulting context into a pointer for use in later decoding */
99 public int
s_jbig2decode_make_global_ctx(byte * data,uint length,Jbig2GlobalCtx ** global_ctx)100 s_jbig2decode_make_global_ctx(byte *data, uint length, Jbig2GlobalCtx **global_ctx)
101 {
102 Jbig2Ctx *ctx = NULL;
103 int code;
104
105 /* the cvision encoder likes to include empty global streams */
106 if (length == 0) {
107 if_debug0('s', "[s] ignoring zero-length jbig2 global stream.\n");
108 *global_ctx = NULL;
109 return 0;
110 }
111
112 /* allocate a context with which to parse our global segments */
113 ctx = jbig2_ctx_new(NULL, JBIG2_OPTIONS_EMBEDDED, NULL,
114 s_jbig2decode_error, NULL);
115
116 /* parse the global bitstream */
117 code = jbig2_data_in(ctx, data, length);
118
119 if (code) {
120 /* error parsing the global stream */
121 *global_ctx = NULL;
122 return code;
123 }
124
125 /* canonize and store our global state */
126 *global_ctx = jbig2_make_global_ctx(ctx);
127
128 return 0; /* todo: check for allocation failure */
129 }
130
131 /* store a global ctx pointer in our state structure */
132 public int
s_jbig2decode_set_global_ctx(stream_state * ss,Jbig2GlobalCtx * global_ctx)133 s_jbig2decode_set_global_ctx(stream_state *ss, Jbig2GlobalCtx *global_ctx)
134 {
135 stream_jbig2decode_state *state = (stream_jbig2decode_state*)ss;
136 state->global_ctx = global_ctx;
137 return 0;
138 }
139
140 /* initialize the steam.
141 this involves allocating the context structures, and
142 initializing the global context from the /JBIG2Globals object reference
143 */
144 private int
s_jbig2decode_init(stream_state * ss)145 s_jbig2decode_init(stream_state * ss)
146 {
147 stream_jbig2decode_state *const state = (stream_jbig2decode_state *) ss;
148 Jbig2GlobalCtx *global_ctx = state->global_ctx; /* may be NULL */
149
150 /* initialize the decoder with the parsed global context if any */
151 state->decode_ctx = jbig2_ctx_new(NULL, JBIG2_OPTIONS_EMBEDDED,
152 global_ctx, s_jbig2decode_error, ss);
153 state->image = 0;
154 state->error = 0;
155 return 0; /* todo: check for allocation failure */
156 }
157
158 /* process a section of the input and return any decoded data.
159 see strimpl.h for return codes.
160 */
161 private int
s_jbig2decode_process(stream_state * ss,stream_cursor_read * pr,stream_cursor_write * pw,bool last)162 s_jbig2decode_process(stream_state * ss, stream_cursor_read * pr,
163 stream_cursor_write * pw, bool last)
164 {
165 stream_jbig2decode_state *const state = (stream_jbig2decode_state *) ss;
166 Jbig2Image *image = state->image;
167 long in_size = pr->limit - pr->ptr;
168 long out_size = pw->limit - pw->ptr;
169 int status = 0;
170
171 /* there will only be a single page image,
172 so pass all data in before looking for any output.
173 note that the gs stream library expects offset-by-one
174 indexing of the buffers, while jbig2dec uses normal 0 indexes */
175 if (in_size > 0) {
176 /* pass all available input to the decoder */
177 jbig2_data_in(state->decode_ctx, pr->ptr + 1, in_size);
178 pr->ptr += in_size;
179 /* simulate end-of-page segment */
180 if (last == 1) {
181 jbig2_complete_page(state->decode_ctx);
182 }
183 /* handle fatal decoding errors reported through our callback */
184 if (state->error) return state->error;
185 }
186 if (out_size > 0) {
187 if (image == NULL) {
188 /* see if a page image in available */
189 image = jbig2_page_out(state->decode_ctx);
190 if (image != NULL) {
191 state->image = image;
192 state->offset = 0;
193 }
194 }
195 if (image != NULL) {
196 /* copy data out of the decoded image, if any */
197 long image_size = image->height*image->stride;
198 long usable = min(image_size - state->offset, out_size);
199 memcpy(pw->ptr + 1, image->data + state->offset, usable);
200 s_jbig2decode_invert_buffer(pw->ptr + 1, usable);
201 state->offset += usable;
202 pw->ptr += usable;
203 status = (state->offset < image_size) ? 1 : 0;
204 }
205 }
206
207 return status;
208 }
209
210 /* stream release.
211 free all our decoder state.
212 */
213 private void
s_jbig2decode_release(stream_state * ss)214 s_jbig2decode_release(stream_state *ss)
215 {
216 stream_jbig2decode_state *const state = (stream_jbig2decode_state *) ss;
217
218 if (state->decode_ctx) {
219 if (state->image) jbig2_release_page(state->decode_ctx, state->image);
220 jbig2_ctx_free(state->decode_ctx);
221 }
222 /* the interpreter takes care of freeing the global_ctx */
223 }
224
225 /* set stream defaults.
226 this hook exists to avoid confusing the gc with bogus
227 pointers. we use it similarly just to NULL all the pointers.
228 (could just be done in _init?)
229 */
230 private void
s_jbig2decode_set_defaults(stream_state * ss)231 s_jbig2decode_set_defaults(stream_state *ss)
232 {
233 stream_jbig2decode_state *const state = (stream_jbig2decode_state *) ss;
234
235 /* state->global_ctx is not owned by us */
236 state->global_ctx = NULL;
237 state->decode_ctx = NULL;
238 state->image = NULL;
239 state->offset = 0;
240 state->error = 0;
241 }
242
243
244 /* stream template */
245 const stream_template s_jbig2decode_template = {
246 &st_jbig2decode_state,
247 s_jbig2decode_init,
248 s_jbig2decode_process,
249 1, 1, /* min in and out buffer sizes we can handle --should be ~32k,64k for efficiency? */
250 s_jbig2decode_release,
251 s_jbig2decode_set_defaults
252 };
253