Go to most recent revision | Details | Last modification | View Log | RSS feed
Rev | Author | Line No. | Line |
---|---|---|---|
4680 | right-hear | 1 | #include "fitz.h" |
2 | |||
3 | #define OPJ_STATIC |
||
4 | #include |
||
5 | |||
6 | static void fz_opj_error_callback(const char *msg, void *client_data) |
||
7 | { |
||
8 | fprintf(stderr, "openjpeg error: %s", msg); |
||
9 | } |
||
10 | |||
11 | static void fz_opj_warning_callback(const char *msg, void *client_data) |
||
12 | { |
||
13 | fprintf(stderr, "openjpeg warning: %s", msg); |
||
14 | } |
||
15 | |||
16 | static void fz_opj_info_callback(const char *msg, void *client_data) |
||
17 | { |
||
18 | /* fprintf(stderr, "openjpeg info: %s", msg); */ |
||
19 | } |
||
20 | |||
21 | fz_error |
||
22 | fz_load_jpx_image(fz_pixmap **imgp, unsigned char *data, int size, fz_colorspace *defcs) |
||
23 | { |
||
24 | fz_pixmap *img; |
||
25 | opj_event_mgr_t evtmgr; |
||
26 | opj_dparameters_t params; |
||
27 | opj_dinfo_t *info; |
||
28 | opj_cio_t *cio; |
||
29 | opj_image_t *jpx; |
||
30 | fz_colorspace *colorspace; |
||
31 | unsigned char *p; |
||
32 | int format; |
||
33 | int a, n, w, h, depth, sgnd; |
||
34 | int x, y, k, v; |
||
35 | |||
36 | if (size < 2) |
||
37 | return fz_throw("not enough data to determine image format"); |
||
38 | |||
39 | /* Check for SOC marker -- if found we have a bare J2K stream */ |
||
40 | if (data[0] == 0xFF && data[1] == 0x4F) |
||
41 | format = CODEC_J2K; |
||
42 | else |
||
43 | format = CODEC_JP2; |
||
44 | |||
45 | memset(&evtmgr, 0, sizeof(evtmgr)); |
||
46 | evtmgr.error_handler = fz_opj_error_callback; |
||
47 | evtmgr.warning_handler = fz_opj_warning_callback; |
||
48 | evtmgr.info_handler = fz_opj_info_callback; |
||
49 | |||
50 | opj_set_default_decoder_parameters(¶ms); |
||
51 | |||
52 | info = opj_create_decompress(format); |
||
53 | opj_set_event_mgr((opj_common_ptr)info, &evtmgr, stderr); |
||
54 | opj_setup_decoder(info, ¶ms); |
||
55 | |||
56 | cio = opj_cio_open((opj_common_ptr)info, data, size); |
||
57 | |||
58 | jpx = opj_decode(info, cio); |
||
59 | |||
60 | opj_cio_close(cio); |
||
61 | opj_destroy_decompress(info); |
||
62 | |||
63 | if (!jpx) |
||
64 | return fz_throw("opj_decode failed"); |
||
65 | |||
66 | for (k = 1; k < jpx->numcomps; k++) |
||
67 | { |
||
68 | if (jpx->comps[k].w != jpx->comps[0].w) |
||
69 | return fz_throw("image components have different width"); |
||
70 | if (jpx->comps[k].h != jpx->comps[0].h) |
||
71 | return fz_throw("image components have different height"); |
||
72 | if (jpx->comps[k].prec != jpx->comps[0].prec) |
||
73 | return fz_throw("image components have different precision"); |
||
74 | } |
||
75 | |||
76 | n = jpx->numcomps; |
||
77 | w = jpx->comps[0].w; |
||
78 | h = jpx->comps[0].h; |
||
79 | depth = jpx->comps[0].prec; |
||
80 | sgnd = jpx->comps[0].sgnd; |
||
81 | |||
82 | if (jpx->color_space == CLRSPC_SRGB && n == 4) { n = 3; a = 1; } |
||
83 | else if (jpx->color_space == CLRSPC_SYCC && n == 4) { n = 3; a = 1; } |
||
84 | else if (n == 2) { n = 1; a = 1; } |
||
85 | else if (n > 4) { n = 4; a = 1; } |
||
86 | else { a = 0; } |
||
87 | |||
88 | if (defcs) |
||
89 | { |
||
90 | if (defcs->n == n) |
||
91 | { |
||
92 | colorspace = defcs; |
||
93 | } |
||
94 | else |
||
95 | { |
||
96 | fz_warn("jpx file and dict colorspaces do not match"); |
||
97 | defcs = NULL; |
||
98 | } |
||
99 | } |
||
100 | |||
101 | if (!defcs) |
||
102 | { |
||
103 | switch (n) |
||
104 | { |
||
105 | case 1: colorspace = fz_device_gray; break; |
||
106 | case 3: colorspace = fz_device_rgb; break; |
||
107 | case 4: colorspace = fz_device_cmyk; break; |
||
108 | } |
||
109 | } |
||
110 | |||
111 | img = fz_new_pixmap_with_limit(colorspace, w, h); |
||
112 | if (!img) |
||
113 | { |
||
114 | opj_image_destroy(jpx); |
||
115 | return fz_throw("out of memory"); |
||
116 | } |
||
117 | |||
118 | p = img->samples; |
||
119 | for (y = 0; y < h; y++) |
||
120 | { |
||
121 | for (x = 0; x < w; x++) |
||
122 | { |
||
123 | for (k = 0; k < n + a; k++) |
||
124 | { |
||
125 | v = jpx->comps[k].data[y * w + x]; |
||
126 | if (sgnd) |
||
127 | v = v + (1 << (depth - 1)); |
||
128 | if (depth > 8) |
||
129 | v = v >> (depth - 8); |
||
130 | *p++ = v; |
||
131 | } |
||
132 | if (!a) |
||
133 | *p++ = 255; |
||
134 | } |
||
135 | } |
||
136 | |||
137 | if (a) |
||
138 | { |
||
139 | if (n == 4) |
||
140 | { |
||
141 | fz_pixmap *tmp = fz_new_pixmap(fz_device_rgb, w, h); |
||
142 | fz_convert_pixmap(img, tmp); |
||
143 | fz_drop_pixmap(img); |
||
144 | img = tmp; |
||
145 | } |
||
146 | fz_premultiply_pixmap(img); |
||
147 | } |
||
148 | |||
149 | opj_image_destroy(jpx); |
||
150 | |||
151 | *imgp = img; |
||
152 | return fz_okay; |
||
153 | }><>>>>>> |