| 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 |