2 |
- |
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
|
|
|
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
|
|
|
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
|
|
|
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
|
|
|
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
|
|
|
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
|
|
|
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
|
|
|
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
|
|
|
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 |
};
|