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