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