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(¶meters); 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, ¶meters) ) { 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