8e77cdaecef7e5fdd98d11f90ab0de0bbe01cb41
[pdfium.git] / core / src / fxcodec / codec / fx_codec_jpx_opj.cpp
1 // Copyright 2014 PDFium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4  
5 // Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com
6
7 #include "../../../include/fxcodec/fx_codec.h"
8 #include "codec_int.h"
9 #include "../fx_libopenjpeg/libopenjpeg20/openjpeg.h"
10 #include "../lcms2/include/fx_lcms2.h"
11 static void fx_error_callback(const char *msg, void *client_data)
12 {
13     (void)client_data;
14 }
15 static void fx_warning_callback(const char *msg, void *client_data)
16 {
17     (void)client_data;
18 }
19 static void fx_info_callback(const char *msg, void *client_data)
20 {
21     (void)client_data;
22 }
23 typedef struct {
24     const unsigned char* src_data;
25     int                                  src_size;
26     int                                  offset;
27 } decodeData;
28 static OPJ_SIZE_T opj_read_from_memory (void * p_buffer, OPJ_SIZE_T p_nb_bytes,  decodeData* srcData)
29 {
30     if(srcData == NULL || srcData->src_size == 0 || srcData->src_data == NULL || srcData->offset >= srcData->src_size) {
31         return -1;
32     }
33     OPJ_SIZE_T readlength = p_nb_bytes;
34     OPJ_SIZE_T bufferLength = (OPJ_SIZE_T)(srcData->src_size - srcData->offset);
35     if(bufferLength <= 0) {
36         return 0;
37     }
38     if(bufferLength <= p_nb_bytes) {
39         readlength = bufferLength;
40     }
41     memcpy(p_buffer, &(srcData->src_data[srcData->offset]), readlength);
42     srcData->offset += (int)readlength;
43     return readlength;
44 }
45 static OPJ_SIZE_T opj_write_from_memory (void * p_buffer, OPJ_SIZE_T p_nb_bytes, decodeData* srcData)
46 {
47     if(srcData == NULL || srcData->src_size == 0 || srcData->src_data == NULL || srcData->offset >= srcData->src_size) {
48         return -1;
49     }
50     OPJ_SIZE_T writeLength = p_nb_bytes;
51     OPJ_SIZE_T bufferLength = (OPJ_SIZE_T)(srcData->src_size - srcData->offset);
52     if(bufferLength <= p_nb_bytes) {
53         writeLength = bufferLength;
54     }
55     memcpy((void*&)(srcData->src_data[srcData->offset]), p_buffer, writeLength);
56     srcData->offset += (int)writeLength;
57     return writeLength;
58 }
59 static OPJ_OFF_T opj_skip_from_memory (OPJ_OFF_T p_nb_bytes, decodeData* srcData)
60 {
61     if(srcData == NULL || srcData->src_size == 0 || srcData->src_data == NULL || srcData->offset >= srcData->src_size) {
62         return -1;
63     }
64     OPJ_OFF_T postion = srcData->offset + p_nb_bytes;
65     if(postion < 0 ) {
66         postion = 0;
67     } else if (postion > srcData->src_size) {
68     }
69     srcData->offset = (int)postion;
70     return p_nb_bytes;
71 }
72 static OPJ_BOOL opj_seek_from_memory (OPJ_OFF_T p_nb_bytes, decodeData * srcData)
73 {
74     if(srcData == NULL || srcData->src_size == 0 || srcData->src_data == NULL || srcData->offset >= srcData->src_size) {
75         return -1;
76     }
77     srcData->offset = (int)p_nb_bytes;
78     if(srcData->offset < 0) {
79         srcData->offset = 0;
80     } else if(srcData->offset > srcData->src_size) {
81         srcData->offset = srcData->src_size;
82     }
83     return OPJ_TRUE;
84 }
85 opj_stream_t* fx_opj_stream_create_memory_stream (decodeData* data,     OPJ_SIZE_T p_size,      OPJ_BOOL p_is_read_stream)
86 {
87     opj_stream_t* l_stream = 00;
88     if (!data || ! data->src_data || data->src_size <= 0 ) {
89         return NULL;
90     }
91     l_stream = opj_stream_create(p_size, p_is_read_stream);
92     if (! l_stream) {
93         return NULL;
94     }
95     opj_stream_set_user_data_v3(l_stream, data, NULL);
96     opj_stream_set_user_data_length(l_stream, data->src_size);
97     opj_stream_set_read_function(l_stream, (opj_stream_read_fn) opj_read_from_memory);
98     opj_stream_set_write_function(l_stream, (opj_stream_write_fn) opj_write_from_memory);
99     opj_stream_set_skip_function(l_stream, (opj_stream_skip_fn) opj_skip_from_memory);
100     opj_stream_set_seek_function(l_stream, (opj_stream_seek_fn) opj_seek_from_memory);
101     return l_stream;
102 }
103 static void sycc_to_rgb(int offset, int upb, int y, int cb, int cr,
104                         int *out_r, int *out_g, int *out_b)
105 {
106     int r, g, b;
107     cb -= offset;
108     cr -= offset;
109     r = y + (int)(1.402 * (float)cr);
110     if(r < 0) {
111         r = 0;
112     } else if(r > upb) {
113         r = upb;
114     } *out_r = r;
115     g = y - (int)(0.344 * (float)cb + 0.714 * (float)cr);
116     if(g < 0) {
117         g = 0;
118     } else if(g > upb) {
119         g = upb;
120     } *out_g = g;
121     b = y + (int)(1.772 * (float)cb);
122     if(b < 0) {
123         b = 0;
124     } else if(b > upb) {
125         b = upb;
126     } *out_b = b;
127 }
128 static void sycc444_to_rgb(opj_image_t *img)
129 {
130     int *d0, *d1, *d2, *r, *g, *b;
131     const int *y, *cb, *cr;
132     int maxw, maxh, max, i, offset, upb;
133     i = (int)img->comps[0].prec;
134     offset = 1 << (i - 1);
135     upb = (1 << i) - 1;
136     maxw = (int)img->comps[0].w;
137     maxh = (int)img->comps[0].h;
138     max = maxw * maxh;
139     y = img->comps[0].data;
140     cb = img->comps[1].data;
141     cr = img->comps[2].data;
142     d0 = r = FX_Alloc(int, (size_t)max);
143     d1 = g = FX_Alloc(int, (size_t)max);
144     d2 = b = FX_Alloc(int, (size_t)max);
145     for(i = 0; i < max; ++i) {
146         sycc_to_rgb(offset, upb, *y, *cb, *cr, r, g, b);
147         ++y;
148         ++cb;
149         ++cr;
150         ++r;
151         ++g;
152         ++b;
153     }
154     FX_Free(img->comps[0].data);
155     img->comps[0].data = d0;
156     FX_Free(img->comps[1].data);
157     img->comps[1].data = d1;
158     FX_Free(img->comps[2].data);
159     img->comps[2].data = d2;
160 }
161 static void sycc422_to_rgb(opj_image_t *img)
162 {
163     int *d0, *d1, *d2, *r, *g, *b;
164     const int *y, *cb, *cr;
165     int maxw, maxh, max, offset, upb;
166     int i, j;
167     i = (int)img->comps[0].prec;
168     offset = 1 << (i - 1);
169     upb = (1 << i) - 1;
170     maxw = (int)img->comps[0].w;
171     maxh = (int)img->comps[0].h;
172     max = maxw * maxh;
173     y = img->comps[0].data;
174     cb = img->comps[1].data;
175     cr = img->comps[2].data;
176     d0 = r = FX_Alloc(int, (size_t)max);
177     d1 = g = FX_Alloc(int, (size_t)max);
178     d2 = b = FX_Alloc(int, (size_t)max);
179     for(i = 0; i < maxh; ++i) {
180         for(j = 0; j < maxw; j += 2) {
181             sycc_to_rgb(offset, upb, *y, *cb, *cr, r, g, b);
182             ++y;
183             ++r;
184             ++g;
185             ++b;
186             sycc_to_rgb(offset, upb, *y, *cb, *cr, r, g, b);
187             ++y;
188             ++r;
189             ++g;
190             ++b;
191             ++cb;
192             ++cr;
193         }
194     }
195     FX_Free(img->comps[0].data);
196     img->comps[0].data = d0;
197     FX_Free(img->comps[1].data);
198     img->comps[1].data = d1;
199     FX_Free(img->comps[2].data);
200     img->comps[2].data = d2;
201     img->comps[1].w = maxw;
202     img->comps[1].h = maxh;
203     img->comps[2].w = maxw;
204     img->comps[2].h = maxh;
205     img->comps[1].w = (OPJ_UINT32)maxw;
206     img->comps[1].h = (OPJ_UINT32)maxh;
207     img->comps[2].w = (OPJ_UINT32)maxw;
208     img->comps[2].h = (OPJ_UINT32)maxh;
209     img->comps[1].dx = img->comps[0].dx;
210     img->comps[2].dx = img->comps[0].dx;
211     img->comps[1].dy = img->comps[0].dy;
212     img->comps[2].dy = img->comps[0].dy;
213 }
214 static void sycc420_to_rgb(opj_image_t *img)
215 {
216     int *d0, *d1, *d2, *r, *g, *b, *nr, *ng, *nb;
217     const int *y, *cb, *cr, *ny;
218     int maxw, maxh, max, offset, upb;
219     int i, j;
220     i = (int)img->comps[0].prec;
221     offset = 1 << (i - 1);
222     upb = (1 << i) - 1;
223     maxw = (int)img->comps[0].w;
224     maxh = (int)img->comps[0].h;
225     max = maxw * maxh;
226     y = img->comps[0].data;
227     cb = img->comps[1].data;
228     cr = img->comps[2].data;
229     d0 = r = FX_Alloc(int, (size_t)max);
230     d1 = g = FX_Alloc(int, (size_t)max);
231     d2 = b = FX_Alloc(int, (size_t)max);
232     for(i = 0; i < maxh; i += 2) {
233         ny = y + maxw;
234         nr = r + maxw;
235         ng = g + maxw;
236         nb = b + maxw;
237         for(j = 0; j < maxw;  j += 2) {
238             sycc_to_rgb(offset, upb, *y, *cb, *cr, r, g, b);
239             ++y;
240             ++r;
241             ++g;
242             ++b;
243             sycc_to_rgb(offset, upb, *y, *cb, *cr, r, g, b);
244             ++y;
245             ++r;
246             ++g;
247             ++b;
248             sycc_to_rgb(offset, upb, *ny, *cb, *cr, nr, ng, nb);
249             ++ny;
250             ++nr;
251             ++ng;
252             ++nb;
253             sycc_to_rgb(offset, upb, *ny, *cb, *cr, nr, ng, nb);
254             ++ny;
255             ++nr;
256             ++ng;
257             ++nb;
258             ++cb;
259             ++cr;
260         }
261         y += maxw;
262         r += maxw;
263         g += maxw;
264         b += maxw;
265     }
266     FX_Free(img->comps[0].data);
267     img->comps[0].data = d0;
268     FX_Free(img->comps[1].data);
269     img->comps[1].data = d1;
270     FX_Free(img->comps[2].data);
271     img->comps[2].data = d2;
272     img->comps[1].w = maxw;
273     img->comps[1].h = maxh;
274     img->comps[2].w = maxw;
275     img->comps[2].h = maxh;
276     img->comps[1].w = (OPJ_UINT32)maxw;
277     img->comps[1].h = (OPJ_UINT32)maxh;
278     img->comps[2].w = (OPJ_UINT32)maxw;
279     img->comps[2].h = (OPJ_UINT32)maxh;
280     img->comps[1].dx = img->comps[0].dx;
281     img->comps[2].dx = img->comps[0].dx;
282     img->comps[1].dy = img->comps[0].dy;
283     img->comps[2].dy = img->comps[0].dy;
284 }
285 void color_sycc_to_rgb(opj_image_t *img)
286 {
287     if(img->numcomps < 3) {
288         img->color_space = OPJ_CLRSPC_GRAY;
289         return;
290     }
291     if((img->comps[0].dx == 1)
292             && (img->comps[1].dx == 2)
293             && (img->comps[2].dx == 2)
294             && (img->comps[0].dy == 1)
295             && (img->comps[1].dy == 2)
296             && (img->comps[2].dy == 2)) {
297         sycc420_to_rgb(img);
298     } else if((img->comps[0].dx == 1)
299               && (img->comps[1].dx == 2)
300               && (img->comps[2].dx == 2)
301               && (img->comps[0].dy == 1)
302               && (img->comps[1].dy == 1)
303               && (img->comps[2].dy == 1)) {
304         sycc422_to_rgb(img);
305     } else if((img->comps[0].dx == 1)
306               && (img->comps[1].dx == 1)
307               && (img->comps[2].dx == 1)
308               && (img->comps[0].dy == 1)
309               && (img->comps[1].dy == 1)
310               && (img->comps[2].dy == 1)) {
311         sycc444_to_rgb(img);
312     } else {
313         return;
314     }
315     img->color_space = OPJ_CLRSPC_SRGB;
316 }
317 void color_apply_icc_profile(opj_image_t *image)
318 {
319     cmsHPROFILE in_prof, out_prof;
320     cmsHTRANSFORM transform;
321     cmsColorSpaceSignature in_space, out_space;
322     cmsUInt32Number intent, in_type, out_type, nr_samples;
323     int *r, *g, *b;
324     int prec, i, max, max_w, max_h;
325     OPJ_COLOR_SPACE oldspace;
326     in_prof =
327         cmsOpenProfileFromMem(image->icc_profile_buf, image->icc_profile_len);
328     if(in_prof == NULL) {
329         return;
330     }
331     in_space = cmsGetPCS(in_prof);
332     out_space = cmsGetColorSpace(in_prof);
333     intent = cmsGetHeaderRenderingIntent(in_prof);
334     max_w = (int)image->comps[0].w;
335     max_h = (int)image->comps[0].h;
336     prec = (int)image->comps[0].prec;
337     oldspace = image->color_space;
338     if(out_space == cmsSigRgbData) {
339         if( prec <= 8 ) {
340             in_type = TYPE_RGB_8;
341             out_type = TYPE_RGB_8;
342         } else {
343             in_type = TYPE_RGB_16;
344             out_type = TYPE_RGB_16;
345         }
346         out_prof = cmsCreate_sRGBProfile();
347         image->color_space = OPJ_CLRSPC_SRGB;
348     } else if(out_space == cmsSigGrayData) {
349         if( prec <= 8 ) {
350             in_type = TYPE_GRAY_8;
351             out_type = TYPE_RGB_8;
352         } else {
353             in_type = TYPE_GRAY_16;
354             out_type = TYPE_RGB_16;
355         }
356         out_prof = cmsCreate_sRGBProfile();
357         image->color_space = OPJ_CLRSPC_SRGB;
358     } else if(out_space == cmsSigYCbCrData) {
359         in_type = TYPE_YCbCr_16;
360         out_type = TYPE_RGB_16;
361         out_prof = cmsCreate_sRGBProfile();
362         image->color_space = OPJ_CLRSPC_SRGB;
363     } else {
364         return;
365     }
366     transform = cmsCreateTransform(in_prof, in_type,
367                                    out_prof, out_type, intent, 0);
368     cmsCloseProfile(in_prof);
369     cmsCloseProfile(out_prof);
370     if(transform == NULL) {
371         image->color_space = oldspace;
372         return;
373     }
374     if(image->numcomps > 2) {
375         if( prec <= 8 ) {
376             unsigned char *inbuf, *outbuf, *in, *out;
377             max = max_w * max_h;
378             nr_samples = (cmsUInt32Number)max * 3 * (cmsUInt32Number)sizeof(unsigned char);
379             in = inbuf = FX_Alloc(unsigned char, nr_samples);
380             out = outbuf = FX_Alloc(unsigned char, nr_samples);
381             r = image->comps[0].data;
382             g = image->comps[1].data;
383             b = image->comps[2].data;
384             for(i = 0; i < max; ++i) {
385                 *in++ = (unsigned char) * r++;
386                 *in++ = (unsigned char) * g++;
387                 *in++ = (unsigned char) * b++;
388             }
389             cmsDoTransform(transform, inbuf, outbuf, (cmsUInt32Number)max);
390             r = image->comps[0].data;
391             g = image->comps[1].data;
392             b = image->comps[2].data;
393             for(i = 0; i < max; ++i) {
394                 *r++ = (int) * out++;
395                 *g++ = (int) * out++;
396                 *b++ = (int) * out++;
397             }
398             FX_Free(inbuf);
399             FX_Free(outbuf);
400         } else {
401             unsigned short *inbuf, *outbuf, *in, *out;
402             max = max_w * max_h;
403             nr_samples = (cmsUInt32Number)max * 3 * (cmsUInt32Number)sizeof(unsigned short);
404             in = inbuf = FX_Alloc(unsigned short, nr_samples);
405             out = outbuf = FX_Alloc(unsigned short, nr_samples);
406             r = image->comps[0].data;
407             g = image->comps[1].data;
408             b = image->comps[2].data;
409             for(i = 0; i < max; ++i) {
410                 *in++ = (unsigned short) * r++;
411                 *in++ = (unsigned short) * g++;
412                 *in++ = (unsigned short) * b++;
413             }
414             cmsDoTransform(transform, inbuf, outbuf, (cmsUInt32Number)max);
415             r = image->comps[0].data;
416             g = image->comps[1].data;
417             b = image->comps[2].data;
418             for(i = 0; i < max; ++i) {
419                 *r++ = (int) * out++;
420                 *g++ = (int) * out++;
421                 *b++ = (int) * out++;
422             }
423             FX_Free(inbuf);
424             FX_Free(outbuf);
425         }
426     } else {
427         unsigned char *in, *inbuf, *out, *outbuf;
428         max = max_w * max_h;
429         nr_samples = (cmsUInt32Number)max * 3 * sizeof(unsigned char);
430         in = inbuf = FX_Alloc(unsigned char, nr_samples);
431         out = outbuf = FX_Alloc(unsigned char, nr_samples);
432         image->comps = (opj_image_comp_t*)
433                        realloc(image->comps, (image->numcomps + 2) * sizeof(opj_image_comp_t));
434         if(image->numcomps == 2) {
435             image->comps[3] = image->comps[1];
436         }
437         image->comps[1] = image->comps[0];
438         image->comps[2] = image->comps[0];
439         image->comps[1].data = FX_Alloc(int, (size_t)max);
440         FXSYS_memset8(image->comps[1].data, 0, sizeof(int) * (size_t)max);
441         image->comps[2].data = FX_Alloc(int, (size_t)max);
442         FXSYS_memset8(image->comps[2].data, 0, sizeof(int) * (size_t)max);
443         image->numcomps += 2;
444         r = image->comps[0].data;
445         for(i = 0; i < max; ++i) {
446             *in++ = (unsigned char) * r++;
447         }
448         cmsDoTransform(transform, inbuf, outbuf, (cmsUInt32Number)max);
449         r = image->comps[0].data;
450         g = image->comps[1].data;
451         b = image->comps[2].data;
452         for(i = 0; i < max; ++i) {
453             *r++ = (int) * out++;
454             *g++ = (int) * out++;
455             *b++ = (int) * out++;
456         }
457         FX_Free(inbuf);
458         FX_Free(outbuf);
459     }
460     cmsDeleteTransform(transform);
461 }
462 void color_apply_conversion(opj_image_t *image)
463 {
464     int *row;
465     int enumcs, numcomps;
466     numcomps = image->numcomps;
467     if(numcomps < 3) {
468         return;
469     }
470     row = (int*)image->icc_profile_buf;
471     enumcs = row[0];
472     if(enumcs == 14) {
473         int *L, *a, *b, *red, *green, *blue, *src0, *src1, *src2;
474         double rl, ol, ra, oa, rb, ob, prec0, prec1, prec2;
475         double minL, maxL, mina, maxa, minb, maxb;
476         unsigned int default_type, il;
477         unsigned int i, max, illu;
478         cmsHPROFILE in, out;
479         cmsHTRANSFORM transform;
480         cmsUInt16Number RGB[3];
481         cmsCIELab Lab;
482         illu = 0;
483         il = 0;
484         in = cmsCreateLab4Profile(NULL);
485         out = cmsCreate_sRGBProfile();
486         transform =
487             cmsCreateTransform(in, TYPE_Lab_DBL, out, TYPE_RGB_16,
488                                INTENT_PERCEPTUAL, 0);
489         cmsCloseProfile(in);
490         cmsCloseProfile(out);
491         if(transform == NULL) {
492             return;
493         }
494         prec0 = (double)image->comps[0].prec;
495         prec1 = (double)image->comps[1].prec;
496         prec2 = (double)image->comps[2].prec;
497         default_type = row[1];
498         if(default_type == 0x44454600) {
499             rl = 100;
500             ra = 170;
501             rb = 200;
502             ol = 0;
503             oa = pow(2, prec1 - 1);
504             ob = pow(2, prec2 - 2)  + pow(2, prec2 - 3);
505         } else {
506             rl = row[2];
507             ra = row[4];
508             rb = row[6];
509             ol = row[3];
510             oa = row[5];
511             ob = row[7];
512         }
513         L = src0 = image->comps[0].data;
514         a = src1 = image->comps[1].data;
515         b = src2 = image->comps[2].data;
516         max = image->comps[0].w * image->comps[0].h;
517         red = FX_Alloc(int, max);
518         image->comps[0].data = red;
519         green = FX_Alloc(int, max);
520         image->comps[1].data = green;
521         blue = FX_Alloc(int, max);
522         image->comps[2].data = blue;
523         minL = -(rl * ol) / (pow(2, prec0) - 1);
524         maxL = minL + rl;
525         mina = -(ra * oa) / (pow(2, prec1) - 1);
526         maxa = mina + ra;
527         minb = -(rb * ob) / (pow(2, prec2) - 1);
528         maxb = minb + rb;
529         for(i = 0; i < max; ++i) {
530             Lab.L = minL + (double)(*L) * (maxL - minL) / (pow(2, prec0) - 1);
531             ++L;
532             Lab.a = mina + (double)(*a) * (maxa - mina) / (pow(2, prec1) - 1);
533             ++a;
534             Lab.b = minb + (double)(*b) * (maxb - minb) / (pow(2, prec2) - 1);
535             ++b;
536             cmsDoTransform(transform, &Lab, RGB, 1);
537             *red++ = RGB[0];
538             *green++ = RGB[1];
539             *blue++ = RGB[2];
540         }
541         cmsDeleteTransform(transform);
542         FX_Free(src0);
543         FX_Free(src1);
544         FX_Free(src2);
545         image->color_space = OPJ_CLRSPC_SRGB;
546         image->comps[0].prec = 16;
547         image->comps[1].prec = 16;
548         image->comps[2].prec = 16;
549         return;
550     }
551 }
552 class CJPX_Decoder : public CFX_Object
553 {
554 public:
555     CJPX_Decoder();
556     ~CJPX_Decoder();
557     FX_BOOL     Init(const unsigned char* src_data, int src_size);
558     void        GetInfo(FX_DWORD& width, FX_DWORD& height, FX_DWORD& codestream_nComps, FX_DWORD& output_nComps);
559     FX_BOOL     Decode(FX_LPBYTE dest_buf, int pitch, FX_BOOL bTranslateColor, FX_LPBYTE offsets);
560     FX_LPCBYTE m_SrcData;
561     int m_SrcSize;
562     opj_image_t *image;
563     opj_codec_t* l_codec;
564     opj_stream_t *l_stream;
565     FX_BOOL m_useColorSpace;
566 };
567 CJPX_Decoder::CJPX_Decoder(): image(NULL), l_codec(NULL), l_stream(NULL), m_useColorSpace(FALSE)
568 {
569 }
570 CJPX_Decoder::~CJPX_Decoder()
571 {
572     if(l_codec) {
573         opj_destroy_codec(l_codec);
574     }
575     if(l_stream) {
576         opj_stream_destroy(l_stream);
577     }
578     if(image) {
579         opj_image_destroy(image);
580     }
581 }
582 FX_BOOL CJPX_Decoder::Init(const unsigned char* src_data, int src_size)
583 {
584     opj_dparameters_t parameters;
585     try {
586         image = NULL;
587         m_SrcData = src_data;
588         m_SrcSize = src_size;
589         decodeData srcData;
590         srcData.offset  = 0;
591         srcData.src_size = src_size;
592         srcData.src_data = src_data;
593         l_stream = fx_opj_stream_create_memory_stream(&srcData, OPJ_J2K_STREAM_CHUNK_SIZE, 1);
594         if (l_stream == NULL) {
595             return FALSE;
596         }
597         opj_set_default_decoder_parameters(&parameters);
598         parameters.decod_format = 0;
599         parameters.cod_format = 3;
600         if(FXSYS_memcmp32(m_SrcData, "\x00\x00\x00\x0c\x6a\x50\x20\x20\x0d\x0a\x87\x0a", 12) == 0) {
601             l_codec = opj_create_decompress(OPJ_CODEC_JP2);
602             parameters.decod_format = 1;
603         } else {
604             l_codec = opj_create_decompress(OPJ_CODEC_J2K);
605         }
606         if(!l_codec) {
607             return FALSE;
608         }
609         opj_set_info_handler(l_codec, fx_info_callback, 00);
610         opj_set_warning_handler(l_codec, fx_warning_callback, 00);
611         opj_set_error_handler(l_codec, fx_error_callback, 00);
612         if ( !opj_setup_decoder(l_codec, &parameters) ) {
613             return FALSE;
614         }
615         if(! opj_read_header(l_stream, l_codec, &image)) {
616             image = NULL;
617             return FALSE;
618         }
619         if(this->m_useColorSpace) {
620             image->useColorSpace = 1;
621         } else {
622             image->useColorSpace = 0;
623         }
624         if (!parameters.nb_tile_to_decode) {
625             if (!opj_set_decode_area(l_codec, image, parameters.DA_x0,
626                                      parameters.DA_y0, parameters.DA_x1, parameters.DA_y1)) {
627                 opj_image_destroy(image);
628                 image = NULL;
629                 return FALSE;
630             }
631             if (!(opj_decode(l_codec, l_stream, image) && opj_end_decompress(l_codec,   l_stream))) {
632                 opj_image_destroy(image);
633                 image = NULL;
634                 return FALSE;
635             }
636         } else {
637             if (!opj_get_decoded_tile(l_codec, l_stream, image, parameters.tile_index)) {
638                 return FALSE;
639             }
640         }
641         opj_stream_destroy(l_stream);
642         l_stream = NULL;
643         if( image->color_space != OPJ_CLRSPC_SYCC
644                 && image->numcomps == 3 && image->comps[0].dx == image->comps[0].dy
645                 && image->comps[1].dx != 1 ) {
646             image->color_space = OPJ_CLRSPC_SYCC;
647         } else if (image->numcomps <= 2) {
648             image->color_space = OPJ_CLRSPC_GRAY;
649         }
650         if(image->color_space == OPJ_CLRSPC_SYCC) {
651             color_sycc_to_rgb(image);
652         }
653         if(image->icc_profile_buf && !image->useColorSpace) {
654             FX_Free(image->icc_profile_buf);
655             image->icc_profile_buf = NULL;
656             image->icc_profile_len = 0;
657         }
658         if(!image) {
659             return FALSE;
660         }
661     } catch (...) {
662         return FALSE;
663     }
664     return TRUE;
665 }
666 void CJPX_Decoder::GetInfo(FX_DWORD& width, FX_DWORD& height, FX_DWORD& codestream_nComps, FX_DWORD& output_nComps)
667 {
668     width = (FX_DWORD)image->x1;
669     height = (FX_DWORD)image->y1;
670     output_nComps = codestream_nComps = (FX_DWORD)image->numcomps;
671 }
672 FX_BOOL CJPX_Decoder::Decode(FX_LPBYTE dest_buf, int pitch, FX_BOOL bTranslateColor, FX_LPBYTE offsets)
673 {
674     FX_BYTE** channel_bufs;
675     int* adjust_comps;
676     int i, wid, hei, row, col, channel, src;
677     FX_BOOL flag;
678     FX_LPBYTE pChannel, pScanline, pPixel;
679     try {
680         if(image->comps[0].w != image->x1 || image->comps[0].h != image->y1) {
681             return FALSE;
682         }
683         if(pitch < (int)(image->comps[0].w * 8 * image->numcomps + 31) >> 5 << 2) {
684             return FALSE;
685         }
686         FXSYS_memset8(dest_buf, 0xff, image->y1 * pitch);
687         channel_bufs = FX_Alloc(FX_BYTE*, image->numcomps);
688         if (channel_bufs == NULL) {
689             return FALSE;
690         }
691         adjust_comps = FX_Alloc(int, image->numcomps);
692         if (adjust_comps == NULL) {
693             FX_Free(channel_bufs);
694             return FALSE;
695         }
696         flag = TRUE;
697         for (i = 0; i < (int)image->numcomps; i ++) {
698             channel_bufs[i] = dest_buf + offsets[i];
699             adjust_comps[i] = image->comps[i].prec - 8;
700             if(i > 0) {
701                 if(image->comps[i].dx != image->comps[i - 1].dx
702                         || image->comps[i].dy != image->comps[i - 1].dy
703                         || image->comps[i].prec != image->comps[i - 1].prec) {
704                     flag = FALSE;
705                     goto failed;
706                 }
707             }
708         }
709         wid = image->comps[0].w;
710         hei = image->comps[0].h;
711         for (channel = 0; channel < (int)image->numcomps; channel++) {
712             pChannel = channel_bufs[channel];
713             if(adjust_comps[channel] < 0) {
714                 for(row = 0; row < hei; row++) {
715                     pScanline = pChannel + row * pitch;
716                     for (col = 0; col < wid; col++) {
717                         pPixel = pScanline + col * image->numcomps;
718                         src = image->comps[channel].data[row * wid + col];
719                         src += image->comps[channel].sgnd ? 1 << (image->comps[channel].prec - 1) : 0;
720                         if (adjust_comps[channel] > 0) {
721                             *pPixel = 0;
722                         } else {
723                             *pPixel = (FX_BYTE)(src << -adjust_comps[channel]);
724                         }
725                     }
726                 }
727             } else {
728                 for(row = 0; row < hei; row++) {
729                     pScanline = pChannel + row * pitch;
730                     for (col = 0; col < wid; col++) {
731                         pPixel = pScanline + col * image->numcomps;
732                         if (!image->comps[channel].data) {
733                             continue;
734                         }
735                         src = image->comps[channel].data[row * wid + col];
736                         src += image->comps[channel].sgnd ? 1 << (image->comps[channel].prec - 1) : 0;
737                         if (adjust_comps[channel] - 1 < 0) {
738                             *pPixel = (FX_BYTE)((src >> adjust_comps[channel]));
739                         } else {
740                             int tmpPixel = (src >> adjust_comps[channel]) + ((src >> (adjust_comps[channel] - 1)) % 2);
741                             if (tmpPixel > 255) {
742                                 tmpPixel = 255;
743                             } else if (tmpPixel < 0) {
744                                 tmpPixel = 0;
745                             }
746                             *pPixel = (FX_BYTE)tmpPixel;
747                         }
748                     }
749                 }
750             }
751         }
752     } catch (...) {
753         if (channel_bufs) {
754             FX_Free(channel_bufs);
755         }
756         FX_Free(adjust_comps);
757         return FALSE;
758     }
759     FX_Free(channel_bufs);
760     FX_Free(adjust_comps);
761     return TRUE;
762 failed:
763     FX_Free(channel_bufs);
764     FX_Free(adjust_comps);
765     return FALSE;
766 }
767 void initialize_transition_table();
768 void initialize_significance_luts();
769 void initialize_sign_lut();
770 CCodec_JpxModule::CCodec_JpxModule()
771 {
772 }
773 void* CCodec_JpxModule::CreateDecoder(FX_LPCBYTE src_buf, FX_DWORD src_size , FX_BOOL useColorSpace)
774 {
775     CJPX_Decoder* pDecoder = FX_NEW CJPX_Decoder;
776     if (pDecoder == NULL) {
777         return NULL;
778     }
779     pDecoder->m_useColorSpace = useColorSpace;
780     if (!pDecoder->Init(src_buf, src_size)) {
781         delete pDecoder;
782         return NULL;
783     }
784     return pDecoder;
785 }
786 void CCodec_JpxModule::GetImageInfo(FX_LPVOID ctx, FX_DWORD& width, FX_DWORD& height,
787                                     FX_DWORD& codestream_nComps, FX_DWORD& output_nComps)
788 {
789     CJPX_Decoder* pDecoder = (CJPX_Decoder*)ctx;
790     pDecoder->GetInfo(width, height, codestream_nComps, output_nComps);
791 }
792 FX_BOOL CCodec_JpxModule::Decode(void* ctx, FX_LPBYTE dest_data, int pitch, FX_BOOL bTranslateColor, FX_LPBYTE offsets)
793 {
794     CJPX_Decoder* pDecoder = (CJPX_Decoder*)ctx;
795     return pDecoder->Decode(dest_data, pitch, bTranslateColor, offsets);
796 }
797 void CCodec_JpxModule::DestroyDecoder(void* ctx)
798 {
799     CJPX_Decoder* pDecoder = (CJPX_Decoder*)ctx;
800     delete pDecoder;
801 }