Merge to XFA: Cleanup: Get rid of CRLF line endings.
[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     {
171         for (j = 0; (OPJ_UINT32)j < (maxw & ~(OPJ_UINT32)1); j += 2)
172         {
173             sycc_to_rgb(offset, upb, *y, *cb, *cr, r, g, b);
174             ++y; ++r; ++g; ++b;
175             sycc_to_rgb(offset, upb, *y, *cb, *cr, r, g, b);
176             ++y; ++r; ++g; ++b; ++cb; ++cr;
177         }
178         if (j < maxw)
179         {
180             sycc_to_rgb(offset, upb, *y, *cb, *cr, r, g, b);
181             ++y; ++r; ++g; ++b; ++cb; ++cr;
182         }
183     }
184     FX_Free(img->comps[0].data);
185     img->comps[0].data = d0;
186     FX_Free(img->comps[1].data);
187     img->comps[1].data = d1;
188     FX_Free(img->comps[2].data);
189     img->comps[2].data = d2;
190     img->comps[1].w = maxw;
191     img->comps[1].h = maxh;
192     img->comps[2].w = maxw;
193     img->comps[2].h = maxh;
194     img->comps[1].w = (OPJ_UINT32)maxw;
195     img->comps[1].h = (OPJ_UINT32)maxh;
196     img->comps[2].w = (OPJ_UINT32)maxw;
197     img->comps[2].h = (OPJ_UINT32)maxh;
198     img->comps[1].dx = img->comps[0].dx;
199     img->comps[2].dx = img->comps[0].dx;
200     img->comps[1].dy = img->comps[0].dy;
201     img->comps[2].dy = img->comps[0].dy;
202 }
203 static void sycc420_to_rgb(opj_image_t *img)
204 {
205     int *d0, *d1, *d2, *r, *g, *b, *nr, *ng, *nb;
206     const int *y, *cb, *cr, *ny;
207     int maxw, maxh, max, offset, upb;
208     int i, j;
209     i = (int)img->comps[0].prec;
210     offset = 1 << (i - 1);
211     upb = (1 << i) - 1;
212     maxw = (int)img->comps[0].w;
213     maxh = (int)img->comps[0].h;
214     max = maxw * maxh;
215     y = img->comps[0].data;
216     cb = img->comps[1].data;
217     cr = img->comps[2].data;
218     d0 = r = FX_Alloc(int, (size_t)max);
219     d1 = g = FX_Alloc(int, (size_t)max);
220     d2 = b = FX_Alloc(int, (size_t)max);
221     for (i = 0; (OPJ_UINT32)i < (maxh & ~(OPJ_UINT32)1); i += 2)
222     {
223         ny = y + maxw;
224         nr = r + maxw;
225         ng = g + maxw;
226         nb = b + maxw;
227         for (j = 0; (OPJ_UINT32)j < (maxw & ~(OPJ_UINT32)1); j += 2)
228         {
229             sycc_to_rgb(offset, upb, *y, *cb, *cr, r, g, b);
230             ++y; ++r; ++g; ++b;
231             sycc_to_rgb(offset, upb, *y, *cb, *cr, r, g, b);
232             ++y; ++r; ++g; ++b;
233             sycc_to_rgb(offset, upb, *ny, *cb, *cr, nr, ng, nb);
234             ++ny; ++nr; ++ng; ++nb;
235             sycc_to_rgb(offset, upb, *ny, *cb, *cr, nr, ng, nb);
236             ++ny; ++nr; ++ng; ++nb; ++cb; ++cr;
237         }
238         if (j < maxw)
239         {
240             sycc_to_rgb(offset, upb, *y, *cb, *cr, r, g, b);
241             ++y; ++r; ++g; ++b;
242             sycc_to_rgb(offset, upb, *ny, *cb, *cr, nr, ng, nb);
243             ++ny; ++nr; ++ng; ++nb; ++cb; ++cr;
244         }
245         y += maxw; r += maxw; g += maxw; b += maxw;
246     }
247     if (i < maxh)
248     {
249         for (j = 0; (OPJ_UINT32)j < (maxw & ~(OPJ_UINT32)1); j += 2)
250         {
251             sycc_to_rgb(offset, upb, *y, *cb, *cr, r, g, b);
252             ++y; ++r; ++g; ++b;
253             sycc_to_rgb(offset, upb, *y, *cb, *cr, r, g, b);
254             ++y; ++r; ++g; ++b; ++cb; ++cr;
255         }
256         if (j < maxw)
257         {
258             sycc_to_rgb(offset, upb, *y, *cb, *cr, r, g, b);
259         }
260     }
261
262     FX_Free(img->comps[0].data);
263     img->comps[0].data = d0;
264     FX_Free(img->comps[1].data);
265     img->comps[1].data = d1;
266     FX_Free(img->comps[2].data);
267     img->comps[2].data = d2;
268     img->comps[1].w = maxw;
269     img->comps[1].h = maxh;
270     img->comps[2].w = maxw;
271     img->comps[2].h = maxh;
272     img->comps[1].w = (OPJ_UINT32)maxw;
273     img->comps[1].h = (OPJ_UINT32)maxh;
274     img->comps[2].w = (OPJ_UINT32)maxw;
275     img->comps[2].h = (OPJ_UINT32)maxh;
276     img->comps[1].dx = img->comps[0].dx;
277     img->comps[2].dx = img->comps[0].dx;
278     img->comps[1].dy = img->comps[0].dy;
279     img->comps[2].dy = img->comps[0].dy;
280 }
281 void color_sycc_to_rgb(opj_image_t *img)
282 {
283     if(img->numcomps < 3) {
284         img->color_space = OPJ_CLRSPC_GRAY;
285         return;
286     }
287     if((img->comps[0].dx == 1)
288             && (img->comps[1].dx == 2)
289             && (img->comps[2].dx == 2)
290             && (img->comps[0].dy == 1)
291             && (img->comps[1].dy == 2)
292             && (img->comps[2].dy == 2)) {
293         sycc420_to_rgb(img);
294     } else 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 == 1)
299               && (img->comps[2].dy == 1)) {
300         sycc422_to_rgb(img);
301     } else if((img->comps[0].dx == 1)
302               && (img->comps[1].dx == 1)
303               && (img->comps[2].dx == 1)
304               && (img->comps[0].dy == 1)
305               && (img->comps[1].dy == 1)
306               && (img->comps[2].dy == 1)) {
307         sycc444_to_rgb(img);
308     } else {
309         return;
310     }
311     img->color_space = OPJ_CLRSPC_SRGB;
312 }
313 void color_apply_icc_profile(opj_image_t *image)
314 {
315     cmsHPROFILE in_prof, out_prof;
316     cmsHTRANSFORM transform;
317     cmsColorSpaceSignature in_space, out_space;
318     cmsUInt32Number intent, in_type, out_type, nr_samples;
319     int *r, *g, *b;
320     int prec, i, max, max_w, max_h;
321     OPJ_COLOR_SPACE oldspace;
322     in_prof =
323         cmsOpenProfileFromMem(image->icc_profile_buf, image->icc_profile_len);
324     if(in_prof == NULL) {
325         return;
326     }
327     in_space = cmsGetPCS(in_prof);
328     out_space = cmsGetColorSpace(in_prof);
329     intent = cmsGetHeaderRenderingIntent(in_prof);
330     max_w = (int)image->comps[0].w;
331     max_h = (int)image->comps[0].h;
332     prec = (int)image->comps[0].prec;
333     oldspace = image->color_space;
334     if(out_space == cmsSigRgbData) {
335         if( prec <= 8 ) {
336             in_type = TYPE_RGB_8;
337             out_type = TYPE_RGB_8;
338         } else {
339             in_type = TYPE_RGB_16;
340             out_type = TYPE_RGB_16;
341         }
342         out_prof = cmsCreate_sRGBProfile();
343         image->color_space = OPJ_CLRSPC_SRGB;
344     } else if(out_space == cmsSigGrayData) {
345         if( prec <= 8 ) {
346             in_type = TYPE_GRAY_8;
347             out_type = TYPE_RGB_8;
348         } else {
349             in_type = TYPE_GRAY_16;
350             out_type = TYPE_RGB_16;
351         }
352         out_prof = cmsCreate_sRGBProfile();
353         image->color_space = OPJ_CLRSPC_SRGB;
354     } else if(out_space == cmsSigYCbCrData) {
355         in_type = TYPE_YCbCr_16;
356         out_type = TYPE_RGB_16;
357         out_prof = cmsCreate_sRGBProfile();
358         image->color_space = OPJ_CLRSPC_SRGB;
359     } else {
360         return;
361     }
362     transform = cmsCreateTransform(in_prof, in_type,
363                                    out_prof, out_type, intent, 0);
364     cmsCloseProfile(in_prof);
365     cmsCloseProfile(out_prof);
366     if(transform == NULL) {
367         image->color_space = oldspace;
368         return;
369     }
370     if(image->numcomps > 2) {
371         if( prec <= 8 ) {
372             unsigned char *inbuf, *outbuf, *in, *out;
373             max = max_w * max_h;
374             nr_samples = (cmsUInt32Number)max * 3 * (cmsUInt32Number)sizeof(unsigned char);
375             in = inbuf = FX_Alloc(unsigned char, nr_samples);
376             out = outbuf = FX_Alloc(unsigned char, nr_samples);
377             r = image->comps[0].data;
378             g = image->comps[1].data;
379             b = image->comps[2].data;
380             for(i = 0; i < max; ++i) {
381                 *in++ = (unsigned char) * r++;
382                 *in++ = (unsigned char) * g++;
383                 *in++ = (unsigned char) * b++;
384             }
385             cmsDoTransform(transform, inbuf, outbuf, (cmsUInt32Number)max);
386             r = image->comps[0].data;
387             g = image->comps[1].data;
388             b = image->comps[2].data;
389             for(i = 0; i < max; ++i) {
390                 *r++ = (int) * out++;
391                 *g++ = (int) * out++;
392                 *b++ = (int) * out++;
393             }
394             FX_Free(inbuf);
395             FX_Free(outbuf);
396         } else {
397             unsigned short *inbuf, *outbuf, *in, *out;
398             max = max_w * max_h;
399             nr_samples = (cmsUInt32Number)max * 3 * (cmsUInt32Number)sizeof(unsigned short);
400             in = inbuf = FX_Alloc(unsigned short, nr_samples);
401             out = outbuf = FX_Alloc(unsigned short, nr_samples);
402             r = image->comps[0].data;
403             g = image->comps[1].data;
404             b = image->comps[2].data;
405             for(i = 0; i < max; ++i) {
406                 *in++ = (unsigned short) * r++;
407                 *in++ = (unsigned short) * g++;
408                 *in++ = (unsigned short) * b++;
409             }
410             cmsDoTransform(transform, inbuf, outbuf, (cmsUInt32Number)max);
411             r = image->comps[0].data;
412             g = image->comps[1].data;
413             b = image->comps[2].data;
414             for(i = 0; i < max; ++i) {
415                 *r++ = (int) * out++;
416                 *g++ = (int) * out++;
417                 *b++ = (int) * out++;
418             }
419             FX_Free(inbuf);
420             FX_Free(outbuf);
421         }
422     } else {
423         unsigned char *in, *inbuf, *out, *outbuf;
424         max = max_w * max_h;
425         nr_samples = (cmsUInt32Number)max * 3 * sizeof(unsigned char);
426         in = inbuf = FX_Alloc(unsigned char, nr_samples);
427         out = outbuf = FX_Alloc(unsigned char, nr_samples);
428         image->comps = (opj_image_comp_t*)
429                        realloc(image->comps, (image->numcomps + 2) * sizeof(opj_image_comp_t));
430         if(image->numcomps == 2) {
431             image->comps[3] = image->comps[1];
432         }
433         image->comps[1] = image->comps[0];
434         image->comps[2] = image->comps[0];
435         image->comps[1].data = FX_Alloc(int, (size_t)max);
436         FXSYS_memset8(image->comps[1].data, 0, sizeof(int) * (size_t)max);
437         image->comps[2].data = FX_Alloc(int, (size_t)max);
438         FXSYS_memset8(image->comps[2].data, 0, sizeof(int) * (size_t)max);
439         image->numcomps += 2;
440         r = image->comps[0].data;
441         for(i = 0; i < max; ++i) {
442             *in++ = (unsigned char) * r++;
443         }
444         cmsDoTransform(transform, inbuf, outbuf, (cmsUInt32Number)max);
445         r = image->comps[0].data;
446         g = image->comps[1].data;
447         b = image->comps[2].data;
448         for(i = 0; i < max; ++i) {
449             *r++ = (int) * out++;
450             *g++ = (int) * out++;
451             *b++ = (int) * out++;
452         }
453         FX_Free(inbuf);
454         FX_Free(outbuf);
455     }
456     cmsDeleteTransform(transform);
457 }
458 void color_apply_conversion(opj_image_t *image)
459 {
460     int *row;
461     int enumcs, numcomps;
462     numcomps = image->numcomps;
463     if(numcomps < 3) {
464         return;
465     }
466     row = (int*)image->icc_profile_buf;
467     enumcs = row[0];
468     if(enumcs == 14) {
469         int *L, *a, *b, *red, *green, *blue, *src0, *src1, *src2;
470         double rl, ol, ra, oa, rb, ob, prec0, prec1, prec2;
471         double minL, maxL, mina, maxa, minb, maxb;
472         unsigned int default_type, il;
473         unsigned int i, max, illu;
474         cmsHPROFILE in, out;
475         cmsHTRANSFORM transform;
476         cmsUInt16Number RGB[3];
477         cmsCIELab Lab;
478         illu = 0;
479         il = 0;
480         in = cmsCreateLab4Profile(NULL);
481         out = cmsCreate_sRGBProfile();
482         transform =
483             cmsCreateTransform(in, TYPE_Lab_DBL, out, TYPE_RGB_16,
484                                INTENT_PERCEPTUAL, 0);
485         cmsCloseProfile(in);
486         cmsCloseProfile(out);
487         if(transform == NULL) {
488             return;
489         }
490         prec0 = (double)image->comps[0].prec;
491         prec1 = (double)image->comps[1].prec;
492         prec2 = (double)image->comps[2].prec;
493         default_type = row[1];
494         if(default_type == 0x44454600) {
495             rl = 100;
496             ra = 170;
497             rb = 200;
498             ol = 0;
499             oa = pow(2, prec1 - 1);
500             ob = pow(2, prec2 - 2)  + pow(2, prec2 - 3);
501         } else {
502             rl = row[2];
503             ra = row[4];
504             rb = row[6];
505             ol = row[3];
506             oa = row[5];
507             ob = row[7];
508         }
509         L = src0 = image->comps[0].data;
510         a = src1 = image->comps[1].data;
511         b = src2 = image->comps[2].data;
512         max = image->comps[0].w * image->comps[0].h;
513         red = FX_Alloc(int, max);
514         image->comps[0].data = red;
515         green = FX_Alloc(int, max);
516         image->comps[1].data = green;
517         blue = FX_Alloc(int, max);
518         image->comps[2].data = blue;
519         minL = -(rl * ol) / (pow(2, prec0) - 1);
520         maxL = minL + rl;
521         mina = -(ra * oa) / (pow(2, prec1) - 1);
522         maxa = mina + ra;
523         minb = -(rb * ob) / (pow(2, prec2) - 1);
524         maxb = minb + rb;
525         for(i = 0; i < max; ++i) {
526             Lab.L = minL + (double)(*L) * (maxL - minL) / (pow(2, prec0) - 1);
527             ++L;
528             Lab.a = mina + (double)(*a) * (maxa - mina) / (pow(2, prec1) - 1);
529             ++a;
530             Lab.b = minb + (double)(*b) * (maxb - minb) / (pow(2, prec2) - 1);
531             ++b;
532             cmsDoTransform(transform, &Lab, RGB, 1);
533             *red++ = RGB[0];
534             *green++ = RGB[1];
535             *blue++ = RGB[2];
536         }
537         cmsDeleteTransform(transform);
538         FX_Free(src0);
539         FX_Free(src1);
540         FX_Free(src2);
541         image->color_space = OPJ_CLRSPC_SRGB;
542         image->comps[0].prec = 16;
543         image->comps[1].prec = 16;
544         image->comps[2].prec = 16;
545         return;
546     }
547 }
548 class CJPX_Decoder : public CFX_Object
549 {
550 public:
551     CJPX_Decoder();
552     ~CJPX_Decoder();
553     FX_BOOL     Init(const unsigned char* src_data, int src_size);
554     void        GetInfo(FX_DWORD& width, FX_DWORD& height, FX_DWORD& codestream_nComps, FX_DWORD& output_nComps);
555     FX_BOOL     Decode(FX_LPBYTE dest_buf, int pitch, FX_BOOL bTranslateColor, FX_LPBYTE offsets);
556     FX_LPCBYTE m_SrcData;
557     int m_SrcSize;
558     opj_image_t *image;
559     opj_codec_t* l_codec;
560     opj_stream_t *l_stream;
561     FX_BOOL m_useColorSpace;
562 };
563 CJPX_Decoder::CJPX_Decoder(): image(NULL), l_codec(NULL), l_stream(NULL), m_useColorSpace(FALSE)
564 {
565 }
566 CJPX_Decoder::~CJPX_Decoder()
567 {
568     if(l_codec) {
569         opj_destroy_codec(l_codec);
570     }
571     if(l_stream) {
572         opj_stream_destroy(l_stream);
573     }
574     if(image) {
575         opj_image_destroy(image);
576     }
577 }
578 FX_BOOL CJPX_Decoder::Init(const unsigned char* src_data, int src_size)
579 {
580     static const unsigned char szJP2Header[] = { 0x00, 0x00, 0x00, 0x0c, 0x6a, 0x50, 0x20, 0x20, 0x0d, 0x0a, 0x87, 0x0a };
581     if (!src_data || src_size < sizeof(szJP2Header)) {
582         return FALSE;
583     }
584     image = NULL;
585     m_SrcData = src_data;
586     m_SrcSize = src_size;
587     DecodeData srcData;
588     srcData.offset  = 0;
589     srcData.src_size = src_size;
590     srcData.src_data = const_cast<unsigned char*>(src_data);
591     l_stream = fx_opj_stream_create_memory_stream(&srcData, OPJ_J2K_STREAM_CHUNK_SIZE, 1);
592     if (l_stream == NULL) {
593         return FALSE;
594     }
595     opj_dparameters_t parameters;
596     opj_set_default_decoder_parameters(&parameters);
597     parameters.decod_format = 0;
598     parameters.cod_format = 3;
599     if(FXSYS_memcmp32(m_SrcData, szJP2Header, sizeof(szJP2Header)) == 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 /*
619     if(this->m_useColorSpace) {
620         image->useColorSpace = 1;
621     } else {
622         image->useColorSpace = 0;
623     }
624 */
625     if (!parameters.nb_tile_to_decode) {
626         if (!opj_set_decode_area(l_codec, image, parameters.DA_x0,
627                                     parameters.DA_y0, parameters.DA_x1, parameters.DA_y1)) {
628             opj_image_destroy(image);
629             image = NULL;
630             return FALSE;
631         }
632         if (!(opj_decode(l_codec, l_stream, image) && opj_end_decompress(l_codec,       l_stream))) {
633             opj_image_destroy(image);
634             image = NULL;
635             return FALSE;
636         }
637     } else {
638         if (!opj_get_decoded_tile(l_codec, l_stream, image, parameters.tile_index)) {
639             return FALSE;
640         }
641     }
642     opj_stream_destroy(l_stream);
643     l_stream = NULL;
644     if( image->color_space != OPJ_CLRSPC_SYCC
645             && image->numcomps == 3 && image->comps[0].dx == image->comps[0].dy
646             && image->comps[1].dx != 1 ) {
647         image->color_space = OPJ_CLRSPC_SYCC;
648     } else if (image->numcomps <= 2) {
649         image->color_space = OPJ_CLRSPC_GRAY;
650     }
651     if(image->color_space == OPJ_CLRSPC_SYCC) {
652         color_sycc_to_rgb(image);
653     }
654     //if(image->icc_profile_buf && !image->useColorSpace) {
655     if(image->icc_profile_buf) {
656         FX_Free(image->icc_profile_buf);
657         image->icc_profile_buf = NULL;
658         image->icc_profile_len = 0;
659     }
660     if(!image) {
661         return FALSE;
662     }
663     return TRUE;
664 }
665 void CJPX_Decoder::GetInfo(FX_DWORD& width, FX_DWORD& height, FX_DWORD& codestream_nComps, FX_DWORD& output_nComps)
666 {
667     width = (FX_DWORD)image->x1;
668     height = (FX_DWORD)image->y1;
669     output_nComps = codestream_nComps = (FX_DWORD)image->numcomps;
670 }
671 FX_BOOL CJPX_Decoder::Decode(FX_LPBYTE dest_buf, int pitch, FX_BOOL bTranslateColor, FX_LPBYTE offsets)
672 {
673     FX_BYTE** channel_bufs;
674     int* adjust_comps;
675     int i, wid, hei, row, col, channel, src;
676     FX_BOOL flag;
677     FX_LPBYTE pChannel, pScanline, pPixel;
678
679     if(image->comps[0].w != image->x1 || image->comps[0].h != image->y1) {
680         return FALSE;
681     }
682     if(pitch < (int)(image->comps[0].w * 8 * image->numcomps + 31) >> 5 << 2) {
683         return FALSE;
684     }
685     FXSYS_memset8(dest_buf, 0xff, image->y1 * pitch);
686     channel_bufs = FX_Alloc(FX_BYTE*, image->numcomps);
687     if (channel_bufs == NULL) {
688         return FALSE;
689     }
690     adjust_comps = FX_Alloc(int, image->numcomps);
691     if (adjust_comps == NULL) {
692         FX_Free(channel_bufs);
693         return FALSE;
694     }
695     flag = TRUE;
696     for (i = 0; i < (int)image->numcomps; i ++) {
697         channel_bufs[i] = dest_buf + offsets[i];
698         adjust_comps[i] = image->comps[i].prec - 8;
699         if(i > 0) {
700             if(image->comps[i].dx != image->comps[i - 1].dx
701                     || image->comps[i].dy != image->comps[i - 1].dy
702                     || image->comps[i].prec != image->comps[i - 1].prec) {
703                 flag = FALSE;
704                 goto failed;
705             }
706         }
707     }
708     wid = image->comps[0].w;
709     hei = image->comps[0].h;
710     for (channel = 0; channel < (int)image->numcomps; channel++) {
711         pChannel = channel_bufs[channel];
712         if(adjust_comps[channel] < 0) {
713             for(row = 0; row < hei; row++) {
714                 pScanline = pChannel + row * pitch;
715                 for (col = 0; col < wid; col++) {
716                     pPixel = pScanline + col * image->numcomps;
717                     src = image->comps[channel].data[row * wid + col];
718                     src += image->comps[channel].sgnd ? 1 << (image->comps[channel].prec - 1) : 0;
719                     if (adjust_comps[channel] > 0) {
720                         *pPixel = 0;
721                     } else {
722                         *pPixel = (FX_BYTE)(src << -adjust_comps[channel]);
723                     }
724                 }
725             }
726         } else {
727             for(row = 0; row < hei; row++) {
728                 pScanline = pChannel + row * pitch;
729                 for (col = 0; col < wid; col++) {
730                     pPixel = pScanline + col * image->numcomps;
731                     if (!image->comps[channel].data) {
732                         continue;
733                     }
734                     src = image->comps[channel].data[row * wid + col];
735                     src += image->comps[channel].sgnd ? 1 << (image->comps[channel].prec - 1) : 0;
736                     if (adjust_comps[channel] - 1 < 0) {
737                         *pPixel = (FX_BYTE)((src >> adjust_comps[channel]));
738                     } else {
739                         int tmpPixel = (src >> adjust_comps[channel]) + ((src >> (adjust_comps[channel] - 1)) % 2);
740                         if (tmpPixel > 255) {
741                             tmpPixel = 255;
742                         } else if (tmpPixel < 0) {
743                             tmpPixel = 0;
744                         }
745                         *pPixel = (FX_BYTE)tmpPixel;
746                     }
747                 }
748             }
749         }
750     }
751
752     FX_Free(channel_bufs);
753     FX_Free(adjust_comps);
754     return TRUE;
755 failed:
756     FX_Free(channel_bufs);
757     FX_Free(adjust_comps);
758     return FALSE;
759 }
760 void initialize_transition_table();
761 void initialize_significance_luts();
762 void initialize_sign_lut();
763 CCodec_JpxModule::CCodec_JpxModule()
764 {
765 }
766 void* CCodec_JpxModule::CreateDecoder(FX_LPCBYTE src_buf, FX_DWORD src_size , FX_BOOL useColorSpace)
767 {
768     CJPX_Decoder* pDecoder = FX_NEW CJPX_Decoder;
769     if (pDecoder == NULL) {
770         return NULL;
771     }
772     pDecoder->m_useColorSpace = useColorSpace;
773     if (!pDecoder->Init(src_buf, src_size)) {
774         delete pDecoder;
775         return NULL;
776     }
777     return pDecoder;
778 }
779 void CCodec_JpxModule::GetImageInfo(FX_LPVOID ctx, FX_DWORD& width, FX_DWORD& height,
780                                     FX_DWORD& codestream_nComps, FX_DWORD& output_nComps)
781 {
782     CJPX_Decoder* pDecoder = (CJPX_Decoder*)ctx;
783     pDecoder->GetInfo(width, height, codestream_nComps, output_nComps);
784 }
785 FX_BOOL CCodec_JpxModule::Decode(void* ctx, FX_LPBYTE dest_data, int pitch, FX_BOOL bTranslateColor, FX_LPBYTE offsets)
786 {
787     CJPX_Decoder* pDecoder = (CJPX_Decoder*)ctx;
788     return pDecoder->Decode(dest_data, pitch, bTranslateColor, offsets);
789 }
790 void CCodec_JpxModule::DestroyDecoder(void* ctx)
791 {
792     CJPX_Decoder* pDecoder = (CJPX_Decoder*)ctx;
793     delete pDecoder;
794 }