Upstream version 9.38.198.0
[platform/framework/web/crosswalk.git] / src / third_party / pdfium / 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     image = NULL;
586     m_SrcData = src_data;
587     m_SrcSize = src_size;
588     decodeData srcData;
589     srcData.offset  = 0;
590     srcData.src_size = src_size;
591     srcData.src_data = src_data;
592     l_stream = fx_opj_stream_create_memory_stream(&srcData, OPJ_J2K_STREAM_CHUNK_SIZE, 1);
593     if (l_stream == NULL) {
594         return FALSE;
595     }
596     opj_set_default_decoder_parameters(&parameters);
597     parameters.decod_format = 0;
598     parameters.cod_format = 3;
599     if(FXSYS_memcmp32(m_SrcData, "\x00\x00\x00\x0c\x6a\x50\x20\x20\x0d\x0a\x87\x0a", 12) == 0) {
600         l_codec = opj_create_decompress(OPJ_CODEC_JP2);
601         parameters.decod_format = 1;
602     } else {
603         l_codec = opj_create_decompress(OPJ_CODEC_J2K);
604     }
605     if(!l_codec) {
606         return FALSE;
607     }
608     opj_set_info_handler(l_codec, fx_info_callback, 00);
609     opj_set_warning_handler(l_codec, fx_warning_callback, 00);
610     opj_set_error_handler(l_codec, fx_error_callback, 00);
611     if ( !opj_setup_decoder(l_codec, &parameters) ) {
612         return FALSE;
613     }
614     if(! opj_read_header(l_stream, l_codec, &image)) {
615         image = NULL;
616         return FALSE;
617     }
618     if(this->m_useColorSpace) {
619         image->useColorSpace = 1;
620     } else {
621         image->useColorSpace = 0;
622     }
623     if (!parameters.nb_tile_to_decode) {
624         if (!opj_set_decode_area(l_codec, image, parameters.DA_x0,
625                                     parameters.DA_y0, parameters.DA_x1, parameters.DA_y1)) {
626             opj_image_destroy(image);
627             image = NULL;
628             return FALSE;
629         }
630         if (!(opj_decode(l_codec, l_stream, image) && opj_end_decompress(l_codec,       l_stream))) {
631             opj_image_destroy(image);
632             image = NULL;
633             return FALSE;
634         }
635     } else {
636         if (!opj_get_decoded_tile(l_codec, l_stream, image, parameters.tile_index)) {
637             return FALSE;
638         }
639     }
640     opj_stream_destroy(l_stream);
641     l_stream = NULL;
642     if( image->color_space != OPJ_CLRSPC_SYCC
643             && image->numcomps == 3 && image->comps[0].dx == image->comps[0].dy
644             && image->comps[1].dx != 1 ) {
645         image->color_space = OPJ_CLRSPC_SYCC;
646     } else if (image->numcomps <= 2) {
647         image->color_space = OPJ_CLRSPC_GRAY;
648     }
649     if(image->color_space == OPJ_CLRSPC_SYCC) {
650         color_sycc_to_rgb(image);
651     }
652     if(image->icc_profile_buf && !image->useColorSpace) {
653         FX_Free(image->icc_profile_buf);
654         image->icc_profile_buf = NULL;
655         image->icc_profile_len = 0;
656     }
657     if(!image) {
658         return FALSE;
659     }
660     return TRUE;
661 }
662 void CJPX_Decoder::GetInfo(FX_DWORD& width, FX_DWORD& height, FX_DWORD& codestream_nComps, FX_DWORD& output_nComps)
663 {
664     width = (FX_DWORD)image->x1;
665     height = (FX_DWORD)image->y1;
666     output_nComps = codestream_nComps = (FX_DWORD)image->numcomps;
667 }
668 FX_BOOL CJPX_Decoder::Decode(FX_LPBYTE dest_buf, int pitch, FX_BOOL bTranslateColor, FX_LPBYTE offsets)
669 {
670     FX_BYTE** channel_bufs;
671     int* adjust_comps;
672     int i, wid, hei, row, col, channel, src;
673     FX_BOOL flag;
674     FX_LPBYTE pChannel, pScanline, pPixel;
675
676     if(image->comps[0].w != image->x1 || image->comps[0].h != image->y1) {
677         return FALSE;
678     }
679     if(pitch < (int)(image->comps[0].w * 8 * image->numcomps + 31) >> 5 << 2) {
680         return FALSE;
681     }
682     FXSYS_memset8(dest_buf, 0xff, image->y1 * pitch);
683     channel_bufs = FX_Alloc(FX_BYTE*, image->numcomps);
684     if (channel_bufs == NULL) {
685         return FALSE;
686     }
687     adjust_comps = FX_Alloc(int, image->numcomps);
688     if (adjust_comps == NULL) {
689         FX_Free(channel_bufs);
690         return FALSE;
691     }
692     flag = TRUE;
693     for (i = 0; i < (int)image->numcomps; i ++) {
694         channel_bufs[i] = dest_buf + offsets[i];
695         adjust_comps[i] = image->comps[i].prec - 8;
696         if(i > 0) {
697             if(image->comps[i].dx != image->comps[i - 1].dx
698                     || image->comps[i].dy != image->comps[i - 1].dy
699                     || image->comps[i].prec != image->comps[i - 1].prec) {
700                 flag = FALSE;
701                 goto failed;
702             }
703         }
704     }
705     wid = image->comps[0].w;
706     hei = image->comps[0].h;
707     for (channel = 0; channel < (int)image->numcomps; channel++) {
708         pChannel = channel_bufs[channel];
709         if(adjust_comps[channel] < 0) {
710             for(row = 0; row < hei; row++) {
711                 pScanline = pChannel + row * pitch;
712                 for (col = 0; col < wid; col++) {
713                     pPixel = pScanline + col * image->numcomps;
714                     src = image->comps[channel].data[row * wid + col];
715                     src += image->comps[channel].sgnd ? 1 << (image->comps[channel].prec - 1) : 0;
716                     if (adjust_comps[channel] > 0) {
717                         *pPixel = 0;
718                     } else {
719                         *pPixel = (FX_BYTE)(src << -adjust_comps[channel]);
720                     }
721                 }
722             }
723         } else {
724             for(row = 0; row < hei; row++) {
725                 pScanline = pChannel + row * pitch;
726                 for (col = 0; col < wid; col++) {
727                     pPixel = pScanline + col * image->numcomps;
728                     if (!image->comps[channel].data) {
729                         continue;
730                     }
731                     src = image->comps[channel].data[row * wid + col];
732                     src += image->comps[channel].sgnd ? 1 << (image->comps[channel].prec - 1) : 0;
733                     if (adjust_comps[channel] - 1 < 0) {
734                         *pPixel = (FX_BYTE)((src >> adjust_comps[channel]));
735                     } else {
736                         int tmpPixel = (src >> adjust_comps[channel]) + ((src >> (adjust_comps[channel] - 1)) % 2);
737                         if (tmpPixel > 255) {
738                             tmpPixel = 255;
739                         } else if (tmpPixel < 0) {
740                             tmpPixel = 0;
741                         }
742                         *pPixel = (FX_BYTE)tmpPixel;
743                     }
744                 }
745             }
746         }
747     }
748
749     FX_Free(channel_bufs);
750     FX_Free(adjust_comps);
751     return TRUE;
752 failed:
753     FX_Free(channel_bufs);
754     FX_Free(adjust_comps);
755     return FALSE;
756 }
757 void initialize_transition_table();
758 void initialize_significance_luts();
759 void initialize_sign_lut();
760 CCodec_JpxModule::CCodec_JpxModule()
761 {
762 }
763 void* CCodec_JpxModule::CreateDecoder(FX_LPCBYTE src_buf, FX_DWORD src_size , FX_BOOL useColorSpace)
764 {
765     CJPX_Decoder* pDecoder = FX_NEW CJPX_Decoder;
766     if (pDecoder == NULL) {
767         return NULL;
768     }
769     pDecoder->m_useColorSpace = useColorSpace;
770     if (!pDecoder->Init(src_buf, src_size)) {
771         delete pDecoder;
772         return NULL;
773     }
774     return pDecoder;
775 }
776 void CCodec_JpxModule::GetImageInfo(FX_LPVOID ctx, FX_DWORD& width, FX_DWORD& height,
777                                     FX_DWORD& codestream_nComps, FX_DWORD& output_nComps)
778 {
779     CJPX_Decoder* pDecoder = (CJPX_Decoder*)ctx;
780     pDecoder->GetInfo(width, height, codestream_nComps, output_nComps);
781 }
782 FX_BOOL CCodec_JpxModule::Decode(void* ctx, FX_LPBYTE dest_data, int pitch, FX_BOOL bTranslateColor, FX_LPBYTE offsets)
783 {
784     CJPX_Decoder* pDecoder = (CJPX_Decoder*)ctx;
785     return pDecoder->Decode(dest_data, pitch, bTranslateColor, offsets);
786 }
787 void CCodec_JpxModule::DestroyDecoder(void* ctx)
788 {
789     CJPX_Decoder* pDecoder = (CJPX_Decoder*)ctx;
790     delete pDecoder;
791 }