2 |
- |
1 |
/* Copyright (C) 2003-2004 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: sjpx.c,v 1.12 2005/03/16 14:57:42 igor Exp $ */
|
|
|
18 |
/* JPXDecode filter implementation -- hooks in libjasper */
|
|
|
19 |
|
|
|
20 |
#include "memory_.h"
|
|
|
21 |
#ifdef JPX_DEBUG
|
|
|
22 |
#include "stdio_.h"
|
|
|
23 |
#endif
|
|
|
24 |
|
|
|
25 |
#include "gserrors.h"
|
|
|
26 |
#include "gserror.h"
|
|
|
27 |
#include "gdebug.h"
|
|
|
28 |
#include "strimpl.h"
|
|
|
29 |
#include "gsmalloc.h"
|
|
|
30 |
#include "sjpx.h"
|
|
|
31 |
|
|
|
32 |
/* stream implementation */
|
|
|
33 |
|
|
|
34 |
/* As with the /JBIG2Decode filter, we let the library do its own
|
|
|
35 |
memory management through malloc() etc. and rely on our release()
|
|
|
36 |
proc being called to deallocate state.
|
|
|
37 |
*/
|
|
|
38 |
|
|
|
39 |
private_st_jpxd_state(); /* creates a gc object for our state,
|
|
|
40 |
defined in sjpx.h */
|
|
|
41 |
|
|
|
42 |
/* initialize the steam.
|
|
|
43 |
this involves allocating the stream and image structures, and
|
|
|
44 |
initializing the decoder.
|
|
|
45 |
*/
|
|
|
46 |
private int
|
|
|
47 |
s_jpxd_init(stream_state * ss)
|
|
|
48 |
{
|
|
|
49 |
stream_jpxd_state *const state = (stream_jpxd_state *) ss;
|
|
|
50 |
int status = 0;
|
|
|
51 |
|
|
|
52 |
state->buffer = NULL;
|
|
|
53 |
state->bufsize = 0;
|
|
|
54 |
state->buffill = 0;
|
|
|
55 |
state->stream = NULL;
|
|
|
56 |
state->image = NULL;
|
|
|
57 |
state->offset = 0;
|
|
|
58 |
state->jpx_memory = ss->memory ? ss->memory->non_gc_memory : gs_lib_ctx_get_non_gc_memory_t();
|
|
|
59 |
|
|
|
60 |
status = jas_init();
|
|
|
61 |
|
|
|
62 |
if (!status) {
|
|
|
63 |
state->buffer = gs_malloc(state->jpx_memory, 4096, 1, "JPXDecode temp buffer");
|
|
|
64 |
status = (state->buffer == NULL);
|
|
|
65 |
}
|
|
|
66 |
if (!status)
|
|
|
67 |
state->bufsize = 4096;
|
|
|
68 |
|
|
|
69 |
return status;
|
|
|
70 |
}
|
|
|
71 |
|
|
|
72 |
#ifdef JPX_DEBUG
|
|
|
73 |
/* dump information from a jasper image struct for debugging */
|
|
|
74 |
private int
|
|
|
75 |
dump_jas_image(jas_image_t *image)
|
|
|
76 |
{
|
|
|
77 |
int i, numcmpts = jas_image_numcmpts(image);
|
|
|
78 |
int clrspc = jas_image_clrspc(image);
|
|
|
79 |
const char *csname = "unrecognized vendor space";
|
|
|
80 |
|
|
|
81 |
if (image == NULL) return 1;
|
|
|
82 |
|
|
|
83 |
dprintf2("JPX image is %d x %d\n",
|
|
|
84 |
jas_image_width(image), jas_image_height(image));
|
|
|
85 |
|
|
|
86 |
/* sort the colorspace */
|
|
|
87 |
if jas_clrspc_isunknown(clrspc) csname = "unknown";
|
|
|
88 |
else switch (clrspc) {
|
|
|
89 |
case JAS_CLRSPC_CIEXYZ: csname = "CIE XYZ"; break;
|
|
|
90 |
case JAS_CLRSPC_CIELAB: csname = "CIE Lab"; break;
|
|
|
91 |
case JAS_CLRSPC_SGRAY: csname = "calibrated grayscale"; break;
|
|
|
92 |
case JAS_CLRSPC_SRGB: csname = "sRGB"; break;
|
|
|
93 |
case JAS_CLRSPC_SYCBCR: csname = "calibrated YCbCr"; break;
|
|
|
94 |
case JAS_CLRSPC_GENGRAY: csname = "generic gray"; break;
|
|
|
95 |
case JAS_CLRSPC_GENRGB: csname = "generic RGB"; break;
|
|
|
96 |
case JAS_CLRSPC_GENYCBCR: csname = "generic YCbCr"; break;
|
|
|
97 |
}
|
|
|
98 |
dprintf3(" colorspace is %s (family %d, member %d)\n",
|
|
|
99 |
csname, jas_clrspc_fam(clrspc), jas_clrspc_mbr(clrspc));
|
|
|
100 |
|
|
|
101 |
for (i = 0; i < numcmpts; i++) {
|
|
|
102 |
int type = jas_image_cmpttype(image, i);
|
|
|
103 |
const char *opacity = (type & JAS_IMAGE_CT_OPACITY) ? " opacity" : "";
|
|
|
104 |
const char *name = "unrecognized";
|
|
|
105 |
const char *issigned = "";
|
|
|
106 |
if (jas_clrspc_fam(clrspc) == JAS_CLRSPC_FAM_GRAY)
|
|
|
107 |
name = "gray";
|
|
|
108 |
else if (jas_clrspc_fam(clrspc) == JAS_CLRSPC_FAM_RGB)
|
|
|
109 |
switch (JAS_IMAGE_CT_COLOR(type)) {
|
|
|
110 |
case JAS_IMAGE_CT_RGB_R: name = "red"; break;
|
|
|
111 |
case JAS_IMAGE_CT_RGB_G: name = "green"; break;
|
|
|
112 |
case JAS_IMAGE_CT_RGB_B: name = "blue"; break;
|
|
|
113 |
case JAS_IMAGE_CT_UNKNOWN:
|
|
|
114 |
default:
|
|
|
115 |
name = "unknown";
|
|
|
116 |
}
|
|
|
117 |
else if (jas_clrspc_fam(clrspc) == JAS_CLRSPC_FAM_YCBCR)
|
|
|
118 |
switch (JAS_IMAGE_CT_COLOR(type)) {
|
|
|
119 |
case JAS_IMAGE_CT_YCBCR_Y: name = "luminance Y"; break;
|
|
|
120 |
case JAS_IMAGE_CT_YCBCR_CB: name = "chrominance Cb"; break;
|
|
|
121 |
case JAS_IMAGE_CT_YCBCR_CR: name = "chrominance Cr"; break;
|
|
|
122 |
case JAS_IMAGE_CT_UNKNOWN:
|
|
|
123 |
default:
|
|
|
124 |
name = "unknown";
|
|
|
125 |
}
|
|
|
126 |
if (jas_image_cmptsgnd(image, i))
|
|
|
127 |
issigned = ", signed";
|
|
|
128 |
dprintf6(" component %d: type %d '%s%s' (%d bits%s)",
|
|
|
129 |
i, type, name, opacity, jas_image_cmptprec(image, i), issigned);
|
|
|
130 |
dprintf4(" grid step (%d,%d) offset (%d,%d)\n",
|
|
|
131 |
jas_image_cmpthstep(image, i), jas_image_cmptvstep(image, i),
|
|
|
132 |
jas_image_cmpttlx(image, i), jas_image_cmpttly(image, i));
|
|
|
133 |
}
|
|
|
134 |
|
|
|
135 |
return 0;
|
|
|
136 |
}
|
|
|
137 |
#endif /* JPX_DEBUG */
|
|
|
138 |
|
|
|
139 |
private int
|
|
|
140 |
copy_row_gray(unsigned char *dest, jas_image_t *image,
|
|
|
141 |
int x, int y, int bytes)
|
|
|
142 |
{
|
|
|
143 |
int i, p;
|
|
|
144 |
int v = jas_image_getcmptbytype(image, JAS_IMAGE_CT_GRAY_Y);
|
|
|
145 |
int shift = max(jas_image_cmptprec(image, v) - 8, 0);
|
|
|
146 |
|
|
|
147 |
for (i = 1; i <= bytes; i++) {
|
|
|
148 |
p = jas_image_readcmptsample(image, v, x++, y);
|
|
|
149 |
dest[i] = p >> shift;
|
|
|
150 |
}
|
|
|
151 |
|
|
|
152 |
return bytes;
|
|
|
153 |
}
|
|
|
154 |
|
|
|
155 |
private int
|
|
|
156 |
copy_row_rgb(unsigned char *dest, jas_image_t *image,
|
|
|
157 |
int x, int y, int bytes)
|
|
|
158 |
{
|
|
|
159 |
int i, p;
|
|
|
160 |
int r = jas_image_getcmptbytype(image, JAS_IMAGE_CT_RGB_R);
|
|
|
161 |
int g = jas_image_getcmptbytype(image, JAS_IMAGE_CT_RGB_G);
|
|
|
162 |
int b = jas_image_getcmptbytype(image, JAS_IMAGE_CT_RGB_B);
|
|
|
163 |
int shift = max(jas_image_cmptprec(image, 0) - 8, 0);
|
|
|
164 |
int count = (bytes/3) * 3;
|
|
|
165 |
|
|
|
166 |
for (i = 1; i <= count; i+=3) {
|
|
|
167 |
p = jas_image_readcmptsample(image, r, x, y);
|
|
|
168 |
dest[i] = p >> shift;
|
|
|
169 |
p = jas_image_readcmptsample(image, g, x, y);
|
|
|
170 |
dest[i+1] = p >> shift;
|
|
|
171 |
p = jas_image_readcmptsample(image, b, x, y);
|
|
|
172 |
dest[i+2] = p >> shift;
|
|
|
173 |
x++;
|
|
|
174 |
}
|
|
|
175 |
|
|
|
176 |
return count;
|
|
|
177 |
}
|
|
|
178 |
|
|
|
179 |
private int
|
|
|
180 |
copy_row_yuv(unsigned char *dest, jas_image_t *image,
|
|
|
181 |
int x, int y, int bytes)
|
|
|
182 |
{
|
|
|
183 |
int i,j;
|
|
|
184 |
int count = (bytes/3) * 3;
|
|
|
185 |
int shift[3];
|
|
|
186 |
int clut[3];
|
|
|
187 |
int hstep[3],vstep[3];
|
|
|
188 |
int p[3],q[3];
|
|
|
189 |
|
|
|
190 |
/* get the component mapping */
|
|
|
191 |
clut[0] = jas_image_getcmptbytype(image, JAS_IMAGE_CT_YCBCR_Y);
|
|
|
192 |
clut[1] = jas_image_getcmptbytype(image, JAS_IMAGE_CT_YCBCR_CB);
|
|
|
193 |
clut[2] = jas_image_getcmptbytype(image, JAS_IMAGE_CT_YCBCR_CR);
|
|
|
194 |
|
|
|
195 |
for (i = 0; i < 3; i++) {
|
|
|
196 |
/* shift each component up to 16 bits */
|
|
|
197 |
shift[i] = 16 - jas_image_cmptprec(image, clut[i]);
|
|
|
198 |
/* repeat subsampled pixels */
|
|
|
199 |
hstep[i] = jas_image_cmpthstep(image, clut[i]);
|
|
|
200 |
vstep[i] = jas_image_cmptvstep(image, clut[i]);
|
|
|
201 |
}
|
|
|
202 |
for (i = 1; i <= count; i+=3) {
|
|
|
203 |
/* read the sample values */
|
|
|
204 |
for (j = 0; j < 3; j++) {
|
|
|
205 |
p[j] = jas_image_readcmptsample(image, clut[j], x/hstep[j], y/vstep[j]);
|
|
|
206 |
p[j] <<= shift[j];
|
|
|
207 |
}
|
|
|
208 |
/* center chroma channels if necessary */
|
|
|
209 |
if (!jas_image_cmptsgnd(image, clut[1])) p[1] -= 0x8000;
|
|
|
210 |
if (!jas_image_cmptsgnd(image, clut[2])) p[2] -= 0x8000;
|
|
|
211 |
/* rotate to RGB */
|
|
|
212 |
#ifdef JPX_USE_IRT
|
|
|
213 |
q[1] = p[0] - ((p[1] + p[2])>>2);
|
|
|
214 |
q[0] = p[1] + q[1];
|
|
|
215 |
q[2] = p[2] + q[1];
|
|
|
216 |
#else
|
|
|
217 |
q[0] = (int)((double)p[0] + 1.402 * p[2]);
|
|
|
218 |
q[1] = (int)((double)p[0] - 0.34413 * p[1] - 0.71414 * p[2]);
|
|
|
219 |
q[2] = (int)((double)p[0] + 1.772 * p[1]);
|
|
|
220 |
#endif
|
|
|
221 |
/* clamp */
|
|
|
222 |
for (j = 0; j < 3; j++){
|
|
|
223 |
if (q[j] < 0) q[j] = 0;
|
|
|
224 |
else if (q[j] > 0xFFFF) q[j] = 0xFFFF;
|
|
|
225 |
}
|
|
|
226 |
/* write out the pixel */
|
|
|
227 |
dest[i] = q[0] >> 8;
|
|
|
228 |
dest[i+1] = q[1] >> 8;
|
|
|
229 |
dest[i+2] = q[2] >> 8;
|
|
|
230 |
x++;
|
|
|
231 |
}
|
|
|
232 |
|
|
|
233 |
return count;
|
|
|
234 |
}
|
|
|
235 |
|
|
|
236 |
private int
|
|
|
237 |
copy_row_default(unsigned char *dest, jas_image_t *image,
|
|
|
238 |
int x, int y, int bytes)
|
|
|
239 |
{
|
|
|
240 |
int i, c,n;
|
|
|
241 |
int count;
|
|
|
242 |
|
|
|
243 |
n = jas_image_numcmpts(image);
|
|
|
244 |
count = (bytes/n) * n;
|
|
|
245 |
for (i = 1; i <= count; i+=n) {
|
|
|
246 |
for (c = 0; c < n; c++)
|
|
|
247 |
dest[i+c] = jas_image_readcmptsample(image, c, x, y);
|
|
|
248 |
x++;
|
|
|
249 |
}
|
|
|
250 |
|
|
|
251 |
return count;
|
|
|
252 |
}
|
|
|
253 |
|
|
|
254 |
/* buffer the input stream into our state */
|
|
|
255 |
private int
|
|
|
256 |
s_jpxd_buffer_input(stream_jpxd_state *const state, stream_cursor_read *pr,
|
|
|
257 |
long bytes)
|
|
|
258 |
{
|
|
|
259 |
/* grow internal buffer if necessary */
|
|
|
260 |
if (bytes > state->bufsize - state->buffill) {
|
|
|
261 |
int newsize = state->bufsize;
|
|
|
262 |
unsigned char *newbuf = NULL;
|
|
|
263 |
while (newsize - state->buffill < bytes)
|
|
|
264 |
newsize <<= 1;
|
|
|
265 |
newbuf = (unsigned char *)gs_malloc(state->jpx_memory, newsize, 1,
|
|
|
266 |
"JPXDecode temp buffer");
|
|
|
267 |
/* TODO: check for allocation failure */
|
|
|
268 |
memcpy(newbuf, state->buffer, state->buffill);
|
|
|
269 |
gs_free(state->jpx_memory, state->buffer, state->bufsize, 1,
|
|
|
270 |
"JPXDecode temp buffer");
|
|
|
271 |
state->buffer = newbuf;
|
|
|
272 |
state->bufsize = newsize;
|
|
|
273 |
}
|
|
|
274 |
|
|
|
275 |
/* copy requested amount of data and return */
|
|
|
276 |
memcpy(state->buffer + state->buffill, pr->ptr + 1, bytes);
|
|
|
277 |
state->buffill += bytes;
|
|
|
278 |
pr->ptr += bytes;
|
|
|
279 |
return bytes;
|
|
|
280 |
}
|
|
|
281 |
|
|
|
282 |
/* decode the compressed image data saved in our state */
|
|
|
283 |
private int
|
|
|
284 |
s_jpxd_decode_image(stream_jpxd_state * state)
|
|
|
285 |
{
|
|
|
286 |
jas_stream_t *stream = state->stream;
|
|
|
287 |
jas_image_t *image = NULL;
|
|
|
288 |
|
|
|
289 |
/* see if an image is available */
|
|
|
290 |
if (stream != NULL) {
|
|
|
291 |
image = jas_image_decode(stream, -1, 0);
|
|
|
292 |
if (image == NULL) {
|
|
|
293 |
dprintf("unable to decode JPX image data.\n");
|
|
|
294 |
return ERRC;
|
|
|
295 |
}
|
|
|
296 |
#ifdef JPX_USE_JASPER_CM
|
|
|
297 |
/* convert non-rgb multicomponent colorspaces to sRGB */
|
|
|
298 |
if (jas_image_numcmpts(image) > 1 &&
|
|
|
299 |
jas_clrspc_fam(jas_image_clrspc(image)) != JAS_CLRSPC_FAM_RGB) {
|
|
|
300 |
jas_cmprof_t *outprof;
|
|
|
301 |
jas_image_t *rgbimage = NULL;
|
|
|
302 |
outprof = jas_cmprof_createfromclrspc(JAS_CLRSPC_SRGB);
|
|
|
303 |
if (outprof != NULL)
|
|
|
304 |
rgbimage = jas_image_chclrspc(image, outprof, JAS_CMXFORM_INTENT_PER);
|
|
|
305 |
if (rgbimage != NULL) {
|
|
|
306 |
jas_image_destroy(image);
|
|
|
307 |
image = rgbimage;
|
|
|
308 |
}
|
|
|
309 |
}
|
|
|
310 |
#endif
|
|
|
311 |
state->image = image;
|
|
|
312 |
state->offset = 0;
|
|
|
313 |
jas_stream_close(stream);
|
|
|
314 |
state->stream = NULL;
|
|
|
315 |
|
|
|
316 |
#ifdef JPX_DEBUG
|
|
|
317 |
dump_jas_image(image);
|
|
|
318 |
#endif
|
|
|
319 |
|
|
|
320 |
}
|
|
|
321 |
|
|
|
322 |
return 0;
|
|
|
323 |
}
|
|
|
324 |
|
|
|
325 |
/* process a secton of the input and return any decoded data.
|
|
|
326 |
see strimpl.h for return codes.
|
|
|
327 |
*/
|
|
|
328 |
private int
|
|
|
329 |
s_jpxd_process(stream_state * ss, stream_cursor_read * pr,
|
|
|
330 |
stream_cursor_write * pw, bool last)
|
|
|
331 |
{
|
|
|
332 |
stream_jpxd_state *const state = (stream_jpxd_state *) ss;
|
|
|
333 |
jas_stream_t *stream = state->stream;
|
|
|
334 |
long in_size = pr->limit - pr->ptr;
|
|
|
335 |
long out_size = pw->limit - pw->ptr;
|
|
|
336 |
int status = 0;
|
|
|
337 |
|
|
|
338 |
/* note that the gs stream library expects offset-by-one
|
|
|
339 |
indexing of its buffers while we use zero indexing */
|
|
|
340 |
|
|
|
341 |
/* JasPer has its own stream library, but there's no public
|
|
|
342 |
api for handing it pieces. We need to add some plumbing
|
|
|
343 |
to convert between gs and jasper streams. In the meantime
|
|
|
344 |
just buffer the entire stream, since it can handle that
|
|
|
345 |
as input. */
|
|
|
346 |
|
|
|
347 |
/* pass all available input to the decoder */
|
|
|
348 |
if (in_size > 0) {
|
|
|
349 |
s_jpxd_buffer_input(state, pr, in_size);
|
|
|
350 |
}
|
|
|
351 |
if ((last == 1) && (stream == NULL) && (state->image == NULL)) {
|
|
|
352 |
/* turn our buffer into a stream */
|
|
|
353 |
stream = jas_stream_memopen((char*)state->buffer, state->bufsize);
|
|
|
354 |
state->stream = stream;
|
|
|
355 |
}
|
|
|
356 |
if (out_size > 0) {
|
|
|
357 |
if (state->image == NULL) {
|
|
|
358 |
status = s_jpxd_decode_image(state);
|
|
|
359 |
}
|
|
|
360 |
if (state->image != NULL) {
|
|
|
361 |
jas_image_t *image = state->image;
|
|
|
362 |
int numcmpts = jas_image_numcmpts(image);
|
|
|
363 |
int stride = numcmpts*jas_image_width(image);
|
|
|
364 |
long image_size = stride*jas_image_height(image);
|
|
|
365 |
int clrspc = jas_image_clrspc(image);
|
|
|
366 |
int x, y;
|
|
|
367 |
long usable, done;
|
|
|
368 |
y = state->offset / stride;
|
|
|
369 |
x = state->offset - y*stride; /* bytes, not samples */
|
|
|
370 |
usable = min(out_size, stride - x);
|
|
|
371 |
x = x/numcmpts; /* now samples */
|
|
|
372 |
/* copy data out of the decoded image data */
|
|
|
373 |
/* be lazy and only write the rest of the current row */
|
|
|
374 |
switch (jas_clrspc_fam(clrspc)) {
|
|
|
375 |
case JAS_CLRSPC_FAM_RGB:
|
|
|
376 |
done = copy_row_rgb(pw->ptr, image, x, y, usable);
|
|
|
377 |
break;
|
|
|
378 |
case JAS_CLRSPC_FAM_YCBCR:
|
|
|
379 |
done = copy_row_yuv(pw->ptr, image, x, y, usable);
|
|
|
380 |
break;
|
|
|
381 |
case JAS_CLRSPC_FAM_GRAY:
|
|
|
382 |
done = copy_row_gray(pw->ptr, image, x, y, usable);
|
|
|
383 |
break;
|
|
|
384 |
case JAS_CLRSPC_FAM_XYZ:
|
|
|
385 |
case JAS_CLRSPC_FAM_LAB:
|
|
|
386 |
case JAS_CLRSPC_FAM_UNKNOWN:
|
|
|
387 |
default:
|
|
|
388 |
done = copy_row_default(pw->ptr, image, x, y, usable);
|
|
|
389 |
break;
|
|
|
390 |
}
|
|
|
391 |
pw->ptr += done;
|
|
|
392 |
state->offset += done;
|
|
|
393 |
status = (state->offset < image_size) ? 1 : 0;
|
|
|
394 |
}
|
|
|
395 |
}
|
|
|
396 |
|
|
|
397 |
return status;
|
|
|
398 |
}
|
|
|
399 |
|
|
|
400 |
/* stream release.
|
|
|
401 |
free all our decoder state.
|
|
|
402 |
*/
|
|
|
403 |
private void
|
|
|
404 |
s_jpxd_release(stream_state *ss)
|
|
|
405 |
{
|
|
|
406 |
stream_jpxd_state *const state = (stream_jpxd_state *) ss;
|
|
|
407 |
|
|
|
408 |
if (state) {
|
|
|
409 |
if (state->image) jas_image_destroy(state->image);
|
|
|
410 |
if (state->stream) jas_stream_close(state->stream);
|
|
|
411 |
if (state->buffer) gs_free(state->jpx_memory, state->buffer, state->bufsize, 1,
|
|
|
412 |
"JPXDecode temp buffer");
|
|
|
413 |
}
|
|
|
414 |
}
|
|
|
415 |
|
|
|
416 |
/* set stream defaults.
|
|
|
417 |
this hook exists to avoid confusing the gc with bogus
|
|
|
418 |
pointers. we use it similarly just to NULL all the pointers.
|
|
|
419 |
(could just be done in _init?)
|
|
|
420 |
*/
|
|
|
421 |
private void
|
|
|
422 |
s_jpxd_set_defaults(stream_state *ss)
|
|
|
423 |
{
|
|
|
424 |
stream_jpxd_state *const state = (stream_jpxd_state *) ss;
|
|
|
425 |
|
|
|
426 |
state->stream = NULL;
|
|
|
427 |
state->image = NULL;
|
|
|
428 |
state->offset = 0;
|
|
|
429 |
state->buffer = NULL;
|
|
|
430 |
state->bufsize = 0;
|
|
|
431 |
state->buffill = 0;
|
|
|
432 |
}
|
|
|
433 |
|
|
|
434 |
|
|
|
435 |
/* stream template */
|
|
|
436 |
const stream_template s_jpxd_template = {
|
|
|
437 |
&st_jpxd_state,
|
|
|
438 |
s_jpxd_init,
|
|
|
439 |
s_jpxd_process,
|
|
|
440 |
1, 1, /* min in and out buffer sizes we can handle
|
|
|
441 |
should be ~32k,64k for efficiency? */
|
|
|
442 |
s_jpxd_release,
|
|
|
443 |
s_jpxd_set_defaults
|
|
|
444 |
};
|