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