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