1#include "mupdf/fitz.h"
2#include "fitz-imp.h"
3
4#include <assert.h>
5#include <string.h>
6
7#if FZ_ENABLE_JPX
8
9typedef struct fz_jpxd_s fz_jpxd;
10typedef struct stream_block_s stream_block;
11
12static void
13jpx_ycc_to_rgb(fz_context *ctx, fz_pixmap *pix, int cbsign, int crsign)
14{
15 int w = pix->w;
16 int h = pix->h;
17 int stride = pix->stride;
18 int x, y;
19
20 for (y = 0; y < h; y++)
21 {
22 unsigned char * row = &pix->samples[stride * y];
23 for (x = 0; x < w; x++)
24 {
25 int ycc[3];
26 ycc[0] = row[x * 3 + 0];
27 ycc[1] = row[x * 3 + 1];
28 ycc[2] = row[x * 3 + 2];
29
30 /* consciously skip Y */
31 if (cbsign)
32 ycc[1] -= 128;
33 if (crsign)
34 ycc[2] -= 128;
35
36 row[x * 3 + 0] = fz_clampi(ycc[0] + 1.402f * ycc[2], 0, 255);
37 row[x * 3 + 1] = fz_clampi(ycc[0] - 0.34413f * ycc[1] - 0.71414f * ycc[2], 0, 255);
38 row[x * 3 + 2] = fz_clampi(ycc[0] + 1.772f * ycc[1], 0, 255);
39 }
40 }
41}
42
43#ifdef HAVE_LURATECH
44
45#include <lwf_jp2.h>
46
47#define MAX_COLORS 4
48#define MAX_ALPHAS 1
49#define MAX_COMPONENTS (MAX_COLORS + MAX_ALPHAS)
50
51#define HAS_PALETTE(cs) ( \
52 (cs) == cJP2_Colorspace_Palette_Gray || \
53 (cs) == cJP2_Colorspace_Palette_RGBa || \
54 (cs) == cJP2_Colorspace_Palette_RGB_YCCa || \
55 (cs) == cJP2_Colorspace_Palette_CIE_LABa || \
56 (cs) == cJP2_Colorspace_Palette_ICCa || \
57 (cs) == cJP2_Colorspace_Palette_CMYKa)
58
59struct fz_jpxd_s
60{
61 fz_pixmap *pix;
62 JP2_Palette_Params *palette;
63 JP2_Property_Value width;
64 JP2_Property_Value height;
65 fz_colorspace *cs;
66 int expand_indexed;
67 unsigned long xres;
68 unsigned long yres;
69 JP2_Property_Value hstep[MAX_COMPONENTS];
70 JP2_Property_Value vstep[MAX_COMPONENTS];
71 JP2_Property_Value bpss[MAX_COMPONENTS];
72 JP2_Property_Value signs[MAX_COMPONENTS];
73};
74
75struct stream_block_s
76{
77 const unsigned char *data;
78 size_t size;
79};
80
81static void * JP2_Callback_Conv
82jpx_alloc(long size, JP2_Callback_Param param)
83{
84 fz_context *ctx = (fz_context *) param;
85 return fz_malloc(ctx, size);
86}
87
88static JP2_Error JP2_Callback_Conv
89jpx_free(void *ptr, JP2_Callback_Param param)
90{
91 fz_context *ctx = (fz_context *) param;
92 fz_free(ctx, ptr);
93 return cJP2_Error_OK;
94}
95
96static unsigned long JP2_Callback_Conv
97jpx_read(unsigned char *pucData,
98 unsigned long ulPos, unsigned long ulSize,
99 JP2_Callback_Param param)
100{
101 stream_block *sb = (stream_block *) param;
102
103 if (ulPos >= sb->size)
104 return 0;
105
106 ulSize = (unsigned long)fz_minz(ulSize, sb->size - ulPos);
107 memcpy(pucData, &sb->data[ulPos], ulSize);
108 return ulSize;
109}
110
111static JP2_Error JP2_Callback_Conv
112jpx_write(unsigned char * pucData, short sComponent, unsigned long ulRow,
113 unsigned long ulStart, unsigned long ulNum, JP2_Callback_Param param)
114{
115 fz_jpxd *state = (fz_jpxd *) param;
116 JP2_Property_Value hstep, vstep;
117 unsigned char *row;
118 int w, h, n, entries, expand;
119 JP2_Property_Value x, y, i, bps, sign;
120 JP2_Property_Value k;
121 unsigned long **palette;
122
123 w = state->pix->w;
124 h = state->pix->h;
125 n = state->pix->n;
126
127 if (ulRow >= (unsigned long)h || ulStart >= (unsigned long)w || sComponent >= n)
128 return cJP2_Error_OK;
129
130 ulNum = fz_mini(ulNum, w - ulStart);
131 hstep = state->hstep[sComponent];
132 vstep = state->vstep[sComponent];
133 bps = state->bpss[sComponent];
134 sign = state->signs[sComponent];
135
136 palette = state->palette ? state->palette->ppulPalette : NULL;
137 entries = state->palette ? state->palette->ulEntries : 1;
138 expand = state->expand_indexed;
139
140 row = state->pix->samples +
141 state->pix->stride * ulRow * vstep +
142 n * ulStart * hstep +
143 sComponent;
144
145 for (y = 0; ulRow * vstep + y < (JP2_Property_Value)h && y < vstep; y++)
146 {
147 unsigned char *p = row;
148
149 for (i = 0; i < ulNum; i++)
150 {
151 for (x = 0; (ulStart + i) * hstep + x < (JP2_Property_Value)w && x < hstep; x++)
152 {
153 if (palette)
154 {
155 unsigned char v = fz_clampi(pucData[i], 0, entries - 1);
156
157 if (expand)
158 {
159 for (k = 0; k < n; k++)
160 p[k] = palette[k][v];
161 }
162 else
163 *p = v;
164 }
165 else
166 {
167 if (bps > 8)
168 {
169 unsigned int v = (pucData[2 * i + 1] << 8) | pucData[2 * i + 0];
170 v &= (1 << bps) - 1;
171 v -= sign;
172 *p = v >> (bps - 8);
173 }
174 else if (bps == 8)
175 {
176 unsigned int v = pucData[i];
177 v &= (1 << bps) - 1;
178 v -= sign;
179 *p = v;
180 }
181 else
182 {
183 unsigned int v = pucData[i];
184 v &= (1 << bps) - 1;
185 v -= sign;
186 *p = v << (8 - bps);
187 }
188 }
189
190 p += n;
191 }
192 }
193
194 row += state->pix->stride;
195 }
196
197 return cJP2_Error_OK;
198}
199
200static fz_pixmap *
201jpx_read_image(fz_context *ctx, fz_jpxd *state, const unsigned char *data, size_t size, fz_colorspace *defcs, int onlymeta)
202{
203 JP2_Decomp_Handle doc;
204 JP2_Channel_Def_Params *chans = NULL;
205 JP2_Error err;
206 int colors, alphas, prealphas;
207 JP2_Property_Value k;
208 JP2_Colorspace colorspace;
209 JP2_Property_Value nchans;
210 JP2_Property_Value widths[MAX_COMPONENTS];
211 JP2_Property_Value heights[MAX_COMPONENTS];
212 stream_block sb;
213
214 memset(state, 0x00, sizeof (fz_jpxd));
215
216 sb.data = data;
217 sb.size = size;
218
219 fz_try(ctx)
220 {
221 err = JP2_Decompress_Start(&doc,
222 jpx_alloc, (JP2_Callback_Param) ctx,
223 jpx_free, (JP2_Callback_Param) ctx,
224 jpx_read, (JP2_Callback_Param) &sb);
225 if (err != cJP2_Error_OK)
226 fz_throw(ctx, FZ_ERROR_GENERIC, "cannot open image: %d", (int) err);
227
228#if defined(JP2_LICENSE_NUM_1) && defined(JP2_LICENSE_NUM_2)
229 err = JP2_Document_SetLicense(doc, JP2_LICENSE_NUM_1, JP2_LICENSE_NUM_2);
230 if (err != cJP2_Error_OK)
231 fz_throw(ctx, FZ_ERROR_GENERIC, "cannot set license: %d", (int) err);
232#endif
233
234 err = JP2_Decompress_GetProp(doc, cJP2_Prop_Extern_Colorspace, (unsigned long *) &colorspace, -1, -1);
235 if (err != cJP2_Error_OK)
236 fz_throw(ctx, FZ_ERROR_GENERIC, "cannot get colorspace: %d", (int) err);
237
238 err = JP2_Decompress_GetChannelDefs(doc, &chans, &nchans);
239 if (err != cJP2_Error_OK)
240 fz_throw(ctx, FZ_ERROR_GENERIC, "cannot get channel definitions: %d", (int) err);
241
242 colors = 0;
243 alphas = 0;
244 prealphas = 0;
245 for (k = 0; k < nchans; k++)
246 {
247 switch (chans[k].ulType)
248 {
249 case cJP2_Channel_Type_Color: colors++; break;
250 case cJP2_Channel_Type_Opacity: alphas++; break;
251 case cJP2_Channel_Type_Opacity_Pre: prealphas++; break;
252 }
253 }
254
255 if (prealphas> 0)
256 alphas = prealphas;
257 colors = fz_clampi(colors, 0, MAX_COLORS);
258 alphas = fz_clampi(alphas, 0, MAX_ALPHAS);
259
260 nchans = colors + alphas;
261
262 if (HAS_PALETTE(colorspace))
263 {
264 err = JP2_Decompress_GetProp(doc, cJP2_Prop_Width, &state->width, -1, 0);
265 if (err != cJP2_Error_OK)
266 fz_throw(ctx, FZ_ERROR_GENERIC, "cannot get width for palette indicies: %d", (int) err);
267 err = JP2_Decompress_GetProp(doc, cJP2_Prop_Height, &state->height, -1, 0);
268 if (err != cJP2_Error_OK)
269 fz_throw(ctx, FZ_ERROR_GENERIC, "cannot get height for palette indicies: %d", (int) err);
270
271 for (k = 0; k < nchans; k++)
272 {
273 widths[k] = state->width;
274 heights[k] = state->height;
275 }
276 }
277 else
278 {
279 for (k = 0; k < nchans; k++)
280 {
281 err = JP2_Decompress_GetProp(doc, cJP2_Prop_Width, &widths[k], -1, k);
282 if (err != cJP2_Error_OK)
283 fz_throw(ctx, FZ_ERROR_GENERIC, "cannot get width for component %d: %d", (int) k, (int) err);
284 err = JP2_Decompress_GetProp(doc, cJP2_Prop_Height, &heights[k], -1, k);
285 if (err != cJP2_Error_OK)
286 fz_throw(ctx, FZ_ERROR_GENERIC, "cannot get height for component %d: %d", (int) k, (int) err);
287
288 state->width = fz_maxi(state->width, widths[k]);
289 state->height = fz_maxi(state->height, heights[k]);
290 }
291 }
292
293 err = JP2_Decompress_GetResolution(doc, &state->yres, &state->xres, NULL,
294 cJP2_Resolution_Dots_Per_Inch, cJP2_Resolution_Capture);
295 if (err != cJP2_Error_OK)
296 fz_throw(ctx, FZ_ERROR_GENERIC, "cannot get resolution: %d", (int) err);
297
298 if (state->xres == 0 || state->yres == 0)
299 state->xres = state->yres = 72;
300
301 state->cs = NULL;
302
303 if (defcs)
304 {
305 if (defcs->n == nchans)
306 state->cs = fz_keep_colorspace(ctx, defcs);
307 else
308 fz_warn(ctx, "jpx file (%lu) and dict colorspace (%d, %s) do not match", nchans, defcs->n, defcs->name);
309 }
310
311#if FZ_ENABLE_ICC
312 if (!state->cs && colorspace == cJP2_Colorspace_Palette_ICCa)
313 {
314 unsigned char *iccprofile = NULL;
315 unsigned long size = 0;
316 fz_buffer *cbuf = NULL;
317 fz_var(cbuf);
318
319 err = JP2_Decompress_GetICC(doc, &iccprofile, &size);
320 if (err != cJP2_Error_OK)
321 fz_throw(ctx, FZ_ERROR_GENERIC, "cannot get ICC color profile: %d", (int) err);
322
323 fz_try(ctx)
324 {
325 cbuf = fz_new_buffer_from_copied_data(ctx, iccprofile, size);
326 state->cs = fz_new_icc_colorspace(ctx, FZ_COLORSPACE_NONE, 0, NULL, cbuf);
327 }
328 fz_always(ctx)
329 fz_drop_buffer(ctx, cbuf);
330 fz_catch(ctx)
331 fz_warn(ctx, "ignoring embedded ICC profile in JPX");
332
333 if (state->cs && state->cs->n != nchans)
334 {
335 fz_warn(ctx, "invalid number of components in ICC profile, ignoring ICC profile in JPX");
336 fz_drop_colorspace(ctx, state->cs);
337 state->cs = NULL;
338 }
339 }
340#endif
341
342 if (!state->cs)
343 {
344 switch (colors)
345 {
346 case 4:
347 state->cs = fz_keep_colorspace(ctx, fz_device_cmyk(ctx));
348 break;
349 case 3:
350 if (colorspace == cJP2_Colorspace_CIE_LABa)
351 state->cs = fz_keep_colorspace(ctx, fz_device_lab(ctx));
352 else
353 state->cs = fz_keep_colorspace(ctx, fz_device_rgb(ctx));
354 break;
355 case 1:
356 state->cs = fz_keep_colorspace(ctx, fz_device_gray(ctx));
357 break;
358 case 0:
359 if (alphas == 1)
360 {
361 /* alpha only images are rendered as grayscale */
362 state->cs = fz_keep_colorspace(ctx, fz_device_gray(ctx));
363 colors = 1;
364 alphas = 0;
365 break;
366 }
367 /* fallthrough */
368 default:
369 fz_throw(ctx, FZ_ERROR_GENERIC, "unsupported number of components: %lu", nchans);
370 }
371 }
372 }
373 fz_catch(ctx)
374 {
375 fz_drop_colorspace(ctx, state->cs);
376 JP2_Decompress_End(doc);
377 fz_rethrow(ctx);
378 }
379
380 if (onlymeta)
381 {
382 JP2_Decompress_End(doc);
383 return NULL;
384 }
385
386 fz_try(ctx)
387 {
388 state->pix = fz_new_pixmap(ctx, state->cs, state->width, state->height, NULL, alphas);
389 fz_clear_pixmap_with_value(ctx, state->pix, 0);
390
391 if (HAS_PALETTE(colorspace))
392 {
393 if (!fz_colorspace_is_indexed(ctx, state->cs))
394 state->expand_indexed = 1;
395
396 err = JP2_Decompress_GetPalette(doc, &state->palette);
397 if (err != cJP2_Error_OK)
398 fz_throw(ctx, FZ_ERROR_GENERIC, "cannot get indexed palette: %d", (int) err);
399
400 /* no available sample file */
401 for (k = 0; k < state->palette->ulChannels; k++)
402 if (state->palette->pucSignedSample[k])
403 fz_throw(ctx, FZ_ERROR_GENERIC, "signed palette components not yet supported");
404 }
405
406 for (k = 0; k < nchans; k++)
407 {
408 state->hstep[k] = (state->width + (widths[k] - 1)) / widths[k];
409 state->vstep[k] = (state->height + (heights[k] - 1)) / heights[k];
410
411 if (HAS_PALETTE(colorspace))
412 {
413 state->bpss[k] = state->palette->pucBitsPerSample[k];
414 state->signs[k] = state->palette->pucSignedSample[k];
415 }
416 else
417 {
418 err = JP2_Decompress_GetProp(doc, cJP2_Prop_Bits_Per_Sample, &state->bpss[k], -1, k);
419 if (err != cJP2_Error_OK)
420 fz_throw(ctx, FZ_ERROR_GENERIC, "cannot get bits per sample for component %d: %d", (int) k, (int) err);
421 err = JP2_Decompress_GetProp(doc, cJP2_Prop_Signed_Samples, &state->signs[k], -1, k);
422 if (err != cJP2_Error_OK)
423 fz_throw(ctx, FZ_ERROR_GENERIC, "cannot get signed for component %d: %d", (int) k, (int) err);
424 }
425 if (state->signs[k])
426 state->signs[k] = 1 << (state->bpss[k] - 1);
427 }
428
429 err = JP2_Decompress_SetProp(doc, cJP2_Prop_Output_Parameter, (JP2_Property_Value) state);
430 if (err != cJP2_Error_OK)
431 fz_throw(ctx, FZ_ERROR_GENERIC, "cannot set write callback userdata: %d", (int) err);
432 err = JP2_Decompress_SetProp(doc, cJP2_Prop_Output_Function, (JP2_Property_Value) jpx_write);
433 if (err != cJP2_Error_OK)
434 fz_throw(ctx, FZ_ERROR_GENERIC, "cannot set write callback: %d", (int) err);
435
436 err = JP2_Decompress_Image(doc);
437 if (err != cJP2_Error_OK)
438 fz_throw(ctx, FZ_ERROR_GENERIC, "cannot decode image: %d", (int) err);
439
440 if (colorspace == cJP2_Colorspace_RGB_YCCa)
441 jpx_ycc_to_rgb(ctx, state->pix, !state->signs[1], !state->signs[2]);
442
443 if (state->pix->alpha && ! (HAS_PALETTE(colorspace) && !state->expand_indexed))
444 {
445 if (alphas > 0 && prealphas == 0)
446 fz_premultiply_pixmap(ctx, state->pix);
447 }
448 }
449 fz_always(ctx)
450 {
451 fz_drop_colorspace(ctx, state->cs);
452 JP2_Decompress_End(doc);
453 }
454 fz_catch(ctx)
455 {
456 fz_drop_pixmap(ctx, state->pix);
457 fz_rethrow(ctx);
458 }
459
460 return state->pix;
461}
462
463fz_pixmap *
464fz_load_jpx(fz_context *ctx, const unsigned char *data, size_t size, fz_colorspace *defcs)
465{
466 fz_jpxd state = { 0 };
467
468 return jpx_read_image(ctx, &state, data, size, defcs, 0);
469}
470
471void
472fz_load_jpx_info(fz_context *ctx, const unsigned char *data, size_t size, int *wp, int *hp, int *xresp, int *yresp, fz_colorspace **cspacep)
473{
474 fz_jpxd state = { 0 };
475
476 jpx_read_image(ctx, &state, data, size, NULL, 1);
477
478 *cspacep = state.cs;
479 *wp = state.width;
480 *hp = state.height;
481 *xresp = state.xres;
482 *yresp = state.yres;
483}
484
485#else /* HAVE_LURATECH */
486
487#include <openjpeg.h>
488
489struct fz_jpxd_s
490{
491 int width;
492 int height;
493 fz_colorspace *cs;
494 int xres;
495 int yres;
496};
497
498struct stream_block_s
499{
500 const unsigned char *data;
501 OPJ_SIZE_T size;
502 OPJ_SIZE_T pos;
503};
504
505/* OpenJPEG does not provide a safe mechanism to intercept
506 * allocations. In the latest version all allocations go
507 * though opj_malloc etc, but no context is passed around.
508 *
509 * In order to ensure that allocations throughout mupdf
510 * are done consistently, we implement opj_malloc etc as
511 * functions that call down to fz_malloc etc. These
512 * require context variables, so we lock and unlock around
513 * calls to openjpeg. Any attempt to call through
514 * without setting these will be detected.
515 *
516 * It is therefore vital that any fz_lock/fz_unlock
517 * handlers are shared between all the fz_contexts in
518 * use at a time.
519 */
520
521/* Potentially we can write different versions
522 * of get_context and set_context for different
523 * threading systems.
524 */
525
526static fz_context *opj_secret = NULL;
527
528static void set_opj_context(fz_context *ctx)
529{
530 opj_secret = ctx;
531}
532
533static fz_context *get_opj_context(void)
534{
535 return opj_secret;
536}
537
538void opj_lock(fz_context *ctx)
539{
540 fz_lock(ctx, FZ_LOCK_FREETYPE);
541
542 set_opj_context(ctx);
543}
544
545void opj_unlock(fz_context *ctx)
546{
547 set_opj_context(NULL);
548
549 fz_unlock(ctx, FZ_LOCK_FREETYPE);
550}
551
552void *opj_malloc(size_t size)
553{
554 fz_context *ctx = get_opj_context();
555
556 assert(ctx != NULL);
557
558 return fz_malloc_no_throw(ctx, size);
559}
560
561void *opj_calloc(size_t n, size_t size)
562{
563 fz_context *ctx = get_opj_context();
564
565 assert(ctx != NULL);
566
567 return fz_calloc_no_throw(ctx, n, size);
568}
569
570void *opj_realloc(void *ptr, size_t size)
571{
572 fz_context *ctx = get_opj_context();
573
574 assert(ctx != NULL);
575
576 return fz_realloc_no_throw(ctx, ptr, size);
577}
578
579void opj_free(void *ptr)
580{
581 fz_context *ctx = get_opj_context();
582
583 assert(ctx != NULL);
584
585 fz_free(ctx, ptr);
586}
587
588static void * opj_aligned_malloc_n(size_t alignment, size_t size)
589{
590 uint8_t *ptr;
591 int off;
592
593 if (size == 0)
594 return NULL;
595
596 size += alignment + sizeof(uint8_t);
597 ptr = opj_malloc(size);
598 if (ptr == NULL)
599 return NULL;
600 off = alignment-(((int)(intptr_t)ptr) & (alignment - 1));
601 ptr[off-1] = off;
602 return ptr + off;
603}
604
605void * opj_aligned_malloc(size_t size)
606{
607 return opj_aligned_malloc_n(16, size);
608}
609
610void * opj_aligned_32_malloc(size_t size)
611{
612 return opj_aligned_malloc_n(32, size);
613}
614
615void opj_aligned_free(void* ptr_)
616{
617 uint8_t *ptr = (uint8_t *)ptr_;
618 uint8_t off;
619 if (ptr == NULL)
620 return;
621
622 off = ptr[-1];
623 opj_free((void *)(((unsigned char *)ptr) - off));
624}
625
626#if 0
627/* UNUSED currently, and moderately tricky, so deferred until required */
628void * opj_aligned_realloc(void *ptr, size_t size)
629{
630 return opj_realloc(ptr, size);
631}
632#endif
633
634static void fz_opj_error_callback(const char *msg, void *client_data)
635{
636 fz_context *ctx = (fz_context *)client_data;
637 char buf[200];
638 int n;
639 fz_strlcpy(buf, msg, sizeof buf);
640 n = strlen(buf);
641 if (buf[n-1] == '\n')
642 buf[n-1] = 0;
643 fz_warn(ctx, "openjpeg error: %s", buf);
644}
645
646static void fz_opj_warning_callback(const char *msg, void *client_data)
647{
648 fz_context *ctx = (fz_context *)client_data;
649 char buf[200];
650 int n;
651 fz_strlcpy(buf, msg, sizeof buf);
652 n = strlen(buf);
653 if (buf[n-1] == '\n')
654 buf[n-1] = 0;
655 fz_warn(ctx, "openjpeg warning: %s", buf);
656}
657
658static void fz_opj_info_callback(const char *msg, void *client_data)
659{
660 /* fz_warn("openjpeg info: %s", msg); */
661}
662
663static OPJ_SIZE_T fz_opj_stream_read(void * p_buffer, OPJ_SIZE_T p_nb_bytes, void * p_user_data)
664{
665 stream_block *sb = (stream_block *)p_user_data;
666 OPJ_SIZE_T len;
667
668 len = sb->size - sb->pos;
669 if (len == 0)
670 return (OPJ_SIZE_T)-1; /* End of file! */
671 if (len > p_nb_bytes)
672 len = p_nb_bytes;
673 memcpy(p_buffer, sb->data + sb->pos, len);
674 sb->pos += len;
675 return len;
676}
677
678static OPJ_OFF_T fz_opj_stream_skip(OPJ_OFF_T skip, void * p_user_data)
679{
680 stream_block *sb = (stream_block *)p_user_data;
681
682 if (skip > (OPJ_OFF_T)(sb->size - sb->pos))
683 skip = (OPJ_OFF_T)(sb->size - sb->pos);
684 sb->pos += skip;
685 return sb->pos;
686}
687
688static OPJ_BOOL fz_opj_stream_seek(OPJ_OFF_T seek_pos, void * p_user_data)
689{
690 stream_block *sb = (stream_block *)p_user_data;
691
692 if (seek_pos > (OPJ_OFF_T)sb->size)
693 return OPJ_FALSE;
694 sb->pos = seek_pos;
695 return OPJ_TRUE;
696}
697
698static fz_pixmap *
699jpx_read_image(fz_context *ctx, fz_jpxd *state, const unsigned char *data, size_t size, fz_colorspace *defcs, int onlymeta)
700{
701 fz_pixmap *img = NULL;
702 opj_dparameters_t params;
703 opj_codec_t *codec;
704 opj_image_t *jpx;
705 opj_stream_t *stream;
706 OPJ_CODEC_FORMAT format;
707 int a, n, w, h;
708 int x, y, k;
709 stream_block sb;
710 OPJ_UINT32 i;
711
712 fz_var(img);
713
714 if (size < 2)
715 fz_throw(ctx, FZ_ERROR_GENERIC, "not enough data to determine image format");
716
717 /* Check for SOC marker -- if found we have a bare J2K stream */
718 if (data[0] == 0xFF && data[1] == 0x4F)
719 format = OPJ_CODEC_J2K;
720 else
721 format = OPJ_CODEC_JP2;
722
723 opj_set_default_decoder_parameters(&params);
724 if (fz_colorspace_is_indexed(ctx, defcs))
725 params.flags |= OPJ_DPARAMETERS_IGNORE_PCLR_CMAP_CDEF_FLAG;
726
727 codec = opj_create_decompress(format);
728 opj_set_info_handler(codec, fz_opj_info_callback, ctx);
729 opj_set_warning_handler(codec, fz_opj_warning_callback, ctx);
730 opj_set_error_handler(codec, fz_opj_error_callback, ctx);
731 if (!opj_setup_decoder(codec, &params))
732 {
733 opj_destroy_codec(codec);
734 fz_throw(ctx, FZ_ERROR_GENERIC, "j2k decode failed");
735 }
736
737 stream = opj_stream_default_create(OPJ_TRUE);
738 sb.data = data;
739 sb.pos = 0;
740 sb.size = size;
741
742 opj_stream_set_read_function(stream, fz_opj_stream_read);
743 opj_stream_set_skip_function(stream, fz_opj_stream_skip);
744 opj_stream_set_seek_function(stream, fz_opj_stream_seek);
745 opj_stream_set_user_data(stream, &sb, NULL);
746 /* Set the length to avoid an assert */
747 opj_stream_set_user_data_length(stream, size);
748
749 if (!opj_read_header(stream, codec, &jpx))
750 {
751 opj_stream_destroy(stream);
752 opj_destroy_codec(codec);
753 fz_throw(ctx, FZ_ERROR_GENERIC, "Failed to read JPX header");
754 }
755
756 if (!opj_decode(codec, stream, jpx))
757 {
758 opj_stream_destroy(stream);
759 opj_destroy_codec(codec);
760 opj_image_destroy(jpx);
761 fz_throw(ctx, FZ_ERROR_GENERIC, "Failed to decode JPX image");
762 }
763
764 opj_stream_destroy(stream);
765 opj_destroy_codec(codec);
766
767 /* jpx should never be NULL here, but check anyway */
768 if (!jpx)
769 fz_throw(ctx, FZ_ERROR_GENERIC, "opj_decode failed");
770
771 /* Count number of alpha and color channels */
772 n = a = 0;
773 for (i = 0; i < jpx->numcomps; ++i)
774 {
775 if (jpx->comps[i].alpha)
776 ++a;
777 else
778 ++n;
779 }
780
781 for (k = 1; k < n + a; k++)
782 {
783 if (!jpx->comps[k].data)
784 {
785 opj_image_destroy(jpx);
786 fz_throw(ctx, FZ_ERROR_GENERIC, "image components are missing data");
787 }
788 }
789
790 state->width = w = jpx->x1 - jpx->x0;
791 state->height = h = jpx->y1 - jpx->y0;
792 state->xres = 72; /* openjpeg does not read the JPEG 2000 resc box */
793 state->yres = 72; /* openjpeg does not read the JPEG 2000 resc box */
794
795 state->cs = NULL;
796
797 if (defcs)
798 {
799 if (defcs->n == n)
800 state->cs = fz_keep_colorspace(ctx, defcs);
801 else
802 fz_warn(ctx, "jpx file and dict colorspace do not match");
803 }
804
805#if FZ_ENABLE_ICC
806 if (!state->cs && jpx->icc_profile_buf)
807 {
808 fz_buffer *cbuf = NULL;
809 fz_var(cbuf);
810
811 fz_try(ctx)
812 {
813 cbuf = fz_new_buffer_from_copied_data(ctx, jpx->icc_profile_buf, jpx->icc_profile_len);
814 state->cs = fz_new_icc_colorspace(ctx, FZ_COLORSPACE_NONE, 0, NULL, cbuf);
815 }
816 fz_always(ctx)
817 fz_drop_buffer(ctx, cbuf);
818 fz_catch(ctx)
819 fz_warn(ctx, "ignoring embedded ICC profile in JPX");
820
821 if (state->cs && state->cs->n != n)
822 {
823 fz_warn(ctx, "invalid number of components in ICC profile, ignoring ICC profile in JPX");
824 fz_drop_colorspace(ctx, state->cs);
825 state->cs = NULL;
826 }
827 }
828#endif
829
830 if (!state->cs)
831 {
832 switch (n)
833 {
834 case 1: state->cs = fz_keep_colorspace(ctx, fz_device_gray(ctx)); break;
835 case 3: state->cs = fz_keep_colorspace(ctx, fz_device_rgb(ctx)); break;
836 case 4: state->cs = fz_keep_colorspace(ctx, fz_device_cmyk(ctx)); break;
837 default:
838 {
839 opj_image_destroy(jpx);
840 fz_throw(ctx, FZ_ERROR_GENERIC, "unsupported number of components: %d", n);
841 }
842 }
843 }
844
845 if (onlymeta)
846 {
847 opj_image_destroy(jpx);
848 return NULL;
849 }
850
851 fz_try(ctx)
852 {
853 unsigned char *samples;
854 int stride, comps;
855
856 a = !!a; /* ignore any superfluous alpha channels */
857 img = fz_new_pixmap(ctx, state->cs, w, h, NULL, a);
858 stride = fz_pixmap_stride(ctx, img);
859 comps = fz_pixmap_components(ctx, img);
860 samples = fz_pixmap_samples(ctx, img);
861
862 fz_clear_pixmap_with_value(ctx, img, 0);
863
864 for (k = 0; k < comps; k++)
865 {
866 opj_image_comp_t *comp = &(jpx->comps[k]);
867 int oy = comp->y0 * comp->dy - jpx->y0;
868 int ox = comp->x0 * comp->dx - jpx->x0;
869
870 if (comp->data == NULL)
871 fz_throw(ctx, FZ_ERROR_GENERIC, "No data for JP2 image component %d", k);
872
873 for (y = 0; y < comp->h; y++)
874 {
875 for (x = 0; x < comp->w; x++)
876 {
877 OPJ_INT32 v;
878 int dx;
879 int dy;
880
881 v = comp->data[y * comp->w + x];
882
883 if (comp->sgnd)
884 v = v + (1 << (comp->prec - 1));
885 if (comp->prec > 8)
886 v = v >> (comp->prec - 8);
887 else if (comp->prec < 8)
888 v = v << (8 - comp->prec);
889
890 for (dy = 0; dy < comp->dy; dy++)
891 {
892 for (dx = 0; dx < comp->dx; dx++)
893 {
894 int xx = ox + x * comp->dx + dx;
895 int yy = oy + y * comp->dy + dy;
896
897 if (xx < w && yy < h)
898 samples[yy * stride + xx * comps + k] = v;
899 }
900 }
901 }
902 }
903 }
904
905 if (jpx->color_space == OPJ_CLRSPC_SYCC && n == 3 && a == 0)
906 jpx_ycc_to_rgb(ctx, img, 1, 1);
907 if (a)
908 fz_premultiply_pixmap(ctx, img);
909 }
910 fz_always(ctx)
911 {
912 fz_drop_colorspace(ctx, state->cs);
913 opj_image_destroy(jpx);
914 }
915 fz_catch(ctx)
916 {
917 fz_drop_pixmap(ctx, img);
918 fz_rethrow(ctx);
919 }
920
921 return img;
922}
923
924fz_pixmap *
925fz_load_jpx(fz_context *ctx, const unsigned char *data, size_t size, fz_colorspace *defcs)
926{
927 fz_jpxd state = { 0 };
928 fz_pixmap *pix = NULL;
929
930 fz_try(ctx)
931 {
932 opj_lock(ctx);
933 pix = jpx_read_image(ctx, &state, data, size, defcs, 0);
934 }
935 fz_always(ctx)
936 opj_unlock(ctx);
937 fz_catch(ctx)
938 fz_rethrow(ctx);
939
940 return pix;
941}
942
943void
944fz_load_jpx_info(fz_context *ctx, const unsigned char *data, size_t size, int *wp, int *hp, int *xresp, int *yresp, fz_colorspace **cspacep)
945{
946 fz_jpxd state = { 0 };
947
948 fz_try(ctx)
949 {
950 opj_lock(ctx);
951 jpx_read_image(ctx, &state, data, size, NULL, 1);
952 }
953 fz_always(ctx)
954 opj_unlock(ctx);
955 fz_catch(ctx)
956 fz_rethrow(ctx);
957
958 *cspacep = state.cs;
959 *wp = state.width;
960 *hp = state.height;
961 *xresp = state.xres;
962 *yresp = state.yres;
963}
964
965#endif /* HAVE_LURATECH */
966
967#else /* FZ_ENABLE_JPX */
968
969fz_pixmap *
970fz_load_jpx(fz_context *ctx, const unsigned char *data, size_t size, fz_colorspace *defcs)
971{
972 fz_throw(ctx, FZ_ERROR_GENERIC, "JPX support disabled");
973}
974
975void
976fz_load_jpx_info(fz_context *ctx, const unsigned char *data, size_t size, int *wp, int *hp, int *xresp, int *yresp, fz_colorspace **cspacep)
977{
978 fz_throw(ctx, FZ_ERROR_GENERIC, "JPX support disabled");
979}
980
981#endif
982