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