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