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