1 // Copyright 2014 PDFium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4
5 // Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com
6
7 #include <algorithm>
8 #include <limits>
9
10 #include "../../../include/fxcodec/fx_codec.h"
11 #include "codec_int.h"
12 #include "../fx_libopenjpeg/libopenjpeg20/openjpeg.h"
13 #include "../lcms2/include/fx_lcms2.h"
14
fx_error_callback(const char * msg,void * client_data)15 static void fx_error_callback(const char *msg, void *client_data)
16 {
17 (void)client_data;
18 }
fx_warning_callback(const char * msg,void * client_data)19 static void fx_warning_callback(const char *msg, void *client_data)
20 {
21 (void)client_data;
22 }
fx_info_callback(const char * msg,void * client_data)23 static void fx_info_callback(const char *msg, void *client_data)
24 {
25 (void)client_data;
26 }
opj_read_from_memory(void * p_buffer,OPJ_SIZE_T nb_bytes,void * p_user_data)27 OPJ_SIZE_T opj_read_from_memory(void* p_buffer, OPJ_SIZE_T nb_bytes, void* p_user_data)
28 {
29 DecodeData* srcData = static_cast<DecodeData*>(p_user_data);
30 if (!srcData || !srcData->src_data || srcData->src_size == 0) {
31 return -1;
32 }
33 // Reads at EOF return an error code.
34 if (srcData->offset >= srcData->src_size) {
35 return -1;
36 }
37 OPJ_SIZE_T bufferLength = srcData->src_size - srcData->offset;
38 OPJ_SIZE_T readlength = nb_bytes < bufferLength ? nb_bytes : bufferLength;
39 memcpy(p_buffer, &srcData->src_data[srcData->offset], readlength);
40 srcData->offset += readlength;
41 return readlength;
42 }
opj_write_from_memory(void * p_buffer,OPJ_SIZE_T nb_bytes,void * p_user_data)43 OPJ_SIZE_T opj_write_from_memory(void* p_buffer, OPJ_SIZE_T nb_bytes, void* p_user_data)
44 {
45 DecodeData* srcData = static_cast<DecodeData*>(p_user_data);
46 if (!srcData || !srcData->src_data || srcData->src_size == 0) {
47 return -1;
48 }
49 // Writes at EOF return an error code.
50 if (srcData->offset >= srcData->src_size) {
51 return -1;
52 }
53 OPJ_SIZE_T bufferLength = srcData->src_size - srcData->offset;
54 OPJ_SIZE_T writeLength = nb_bytes < bufferLength ? nb_bytes : bufferLength;
55 memcpy(&srcData->src_data[srcData->offset], p_buffer, writeLength);
56 srcData->offset += writeLength;
57 return writeLength;
58 }
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)
60 {
61 DecodeData* srcData = static_cast<DecodeData*>(p_user_data);
62 if (!srcData || !srcData->src_data || srcData->src_size == 0) {
63 return -1;
64 }
65 // Offsets are signed and may indicate a negative skip. Do not support this
66 // because of the strange return convention where either bytes skipped or
67 // -1 is returned. Following that convention, a successful relative seek of
68 // -1 bytes would be required to to give the same result as the error case.
69 if (nb_bytes < 0) {
70 return -1;
71 }
72 // FIXME: use std::make_unsigned<OPJ_OFF_T>::type once c++11 lib is OK'd.
73 uint64_t unsignedNbBytes = static_cast<uint64_t>(nb_bytes);
74 // Additionally, the offset may take us beyond the range of a size_t (e.g.
75 // 32-bit platforms). If so, just clamp at EOF.
76 if (unsignedNbBytes > std::numeric_limits<OPJ_SIZE_T>::max() - srcData->offset) {
77 srcData->offset = srcData->src_size;
78 } else {
79 OPJ_SIZE_T checkedNbBytes = static_cast<OPJ_SIZE_T>(unsignedNbBytes);
80 // Otherwise, mimic fseek() semantics to always succeed, even past EOF,
81 // clamping at EOF. We can get away with this since we don't actually
82 // provide negative relative skips from beyond EOF back to inside the
83 // data, which would be the only reason to need to know exactly how far
84 // beyond EOF we are.
85 srcData->offset = std::min(srcData->offset + checkedNbBytes, srcData->src_size);
86 }
87 return nb_bytes;
88 }
opj_seek_from_memory(OPJ_OFF_T nb_bytes,void * p_user_data)89 OPJ_BOOL opj_seek_from_memory(OPJ_OFF_T nb_bytes, void* p_user_data)
90 {
91 DecodeData* srcData = static_cast<DecodeData*>(p_user_data);
92 if (!srcData || !srcData->src_data || srcData->src_size == 0) {
93 return OPJ_FALSE;
94 }
95 // Offsets are signed and may indicate a negative position, which would
96 // be before the start of the file. Do not support this.
97 if (nb_bytes < 0) {
98 return OPJ_FALSE;
99 }
100 // FIXME: use std::make_unsigned<OPJ_OFF_T>::type once c++11 lib is OK'd.
101 uint64_t unsignedNbBytes = static_cast<uint64_t>(nb_bytes);
102 // Additionally, the offset may take us beyond the range of a size_t (e.g.
103 // 32-bit platforms). If so, just clamp at EOF.
104 if (unsignedNbBytes > std::numeric_limits<OPJ_SIZE_T>::max()) {
105 srcData->offset = srcData->src_size;
106 } else {
107 OPJ_SIZE_T checkedNbBytes = static_cast<OPJ_SIZE_T>(nb_bytes);
108 // Otherwise, mimic fseek() semantics to always succeed, even past EOF,
109 // again clamping at EOF.
110 srcData->offset = std::min(checkedNbBytes, srcData->src_size);
111 }
112 return OPJ_TRUE;
113 }
fx_opj_stream_create_memory_stream(DecodeData * data,OPJ_SIZE_T p_size,OPJ_BOOL p_is_read_stream)114 opj_stream_t* fx_opj_stream_create_memory_stream (DecodeData* data, OPJ_SIZE_T p_size, OPJ_BOOL p_is_read_stream)
115 {
116 opj_stream_t* l_stream = 00;
117 if (!data || ! data->src_data || data->src_size <= 0 ) {
118 return NULL;
119 }
120 l_stream = opj_stream_create(p_size, p_is_read_stream);
121 if (! l_stream) {
122 return NULL;
123 }
124 opj_stream_set_user_data(l_stream, data, NULL);
125 opj_stream_set_user_data_length(l_stream, data->src_size);
126 opj_stream_set_read_function(l_stream, opj_read_from_memory);
127 opj_stream_set_write_function(l_stream, opj_write_from_memory);
128 opj_stream_set_skip_function(l_stream, opj_skip_from_memory);
129 opj_stream_set_seek_function(l_stream, opj_seek_from_memory);
130 return l_stream;
131 }
sycc_to_rgb(int offset,int upb,int y,int cb,int cr,int * out_r,int * out_g,int * out_b)132 static void sycc_to_rgb(int offset, int upb, int y, int cb, int cr,
133 int *out_r, int *out_g, int *out_b)
134 {
135 int r, g, b;
136 cb -= offset;
137 cr -= offset;
138 r = y + (int)(1.402 * (float)cr);
139 if(r < 0) {
140 r = 0;
141 } else if(r > upb) {
142 r = upb;
143 } *out_r = r;
144 g = y - (int)(0.344 * (float)cb + 0.714 * (float)cr);
145 if(g < 0) {
146 g = 0;
147 } else if(g > upb) {
148 g = upb;
149 } *out_g = g;
150 b = y + (int)(1.772 * (float)cb);
151 if(b < 0) {
152 b = 0;
153 } else if(b > upb) {
154 b = upb;
155 } *out_b = b;
156 }
sycc444_to_rgb(opj_image_t * img)157 static void sycc444_to_rgb(opj_image_t *img)
158 {
159 int *d0, *d1, *d2, *r, *g, *b;
160 const int *y, *cb, *cr;
161 int maxw, maxh, max, i, offset, upb;
162 i = (int)img->comps[0].prec;
163 offset = 1 << (i - 1);
164 upb = (1 << i) - 1;
165 maxw = (int)img->comps[0].w;
166 maxh = (int)img->comps[0].h;
167 max = maxw * maxh;
168 y = img->comps[0].data;
169 cb = img->comps[1].data;
170 cr = img->comps[2].data;
171 d0 = r = FX_Alloc(int, (size_t)max);
172 d1 = g = FX_Alloc(int, (size_t)max);
173 d2 = b = FX_Alloc(int, (size_t)max);
174 for(i = 0; i < max; ++i) {
175 sycc_to_rgb(offset, upb, *y, *cb, *cr, r, g, b);
176 ++y;
177 ++cb;
178 ++cr;
179 ++r;
180 ++g;
181 ++b;
182 }
183 FX_Free(img->comps[0].data);
184 img->comps[0].data = d0;
185 FX_Free(img->comps[1].data);
186 img->comps[1].data = d1;
187 FX_Free(img->comps[2].data);
188 img->comps[2].data = d2;
189 }
sycc422_to_rgb(opj_image_t * img)190 static void sycc422_to_rgb(opj_image_t *img)
191 {
192 int *d0, *d1, *d2, *r, *g, *b;
193 const int *y, *cb, *cr;
194 int maxw, maxh, max, offset, upb;
195 int i, j;
196 i = (int)img->comps[0].prec;
197 offset = 1 << (i - 1);
198 upb = (1 << i) - 1;
199 maxw = (int)img->comps[0].w;
200 maxh = (int)img->comps[0].h;
201 max = maxw * maxh;
202 y = img->comps[0].data;
203 cb = img->comps[1].data;
204 cr = img->comps[2].data;
205 d0 = r = FX_Alloc(int, (size_t)max);
206 d1 = g = FX_Alloc(int, (size_t)max);
207 d2 = b = FX_Alloc(int, (size_t)max);
208 for(i = 0; i < maxh; ++i)
209 {
210 for (j = 0; (OPJ_UINT32)j < (maxw & ~(OPJ_UINT32)1); j += 2)
211 {
212 sycc_to_rgb(offset, upb, *y, *cb, *cr, r, g, b);
213 ++y; ++r; ++g; ++b;
214 sycc_to_rgb(offset, upb, *y, *cb, *cr, r, g, b);
215 ++y; ++r; ++g; ++b; ++cb; ++cr;
216 }
217 if (j < maxw)
218 {
219 sycc_to_rgb(offset, upb, *y, *cb, *cr, r, g, b);
220 ++y; ++r; ++g; ++b; ++cb; ++cr;
221 }
222 }
223 FX_Free(img->comps[0].data);
224 img->comps[0].data = d0;
225 FX_Free(img->comps[1].data);
226 img->comps[1].data = d1;
227 FX_Free(img->comps[2].data);
228 img->comps[2].data = d2;
229 img->comps[1].w = maxw;
230 img->comps[1].h = maxh;
231 img->comps[2].w = maxw;
232 img->comps[2].h = maxh;
233 img->comps[1].w = (OPJ_UINT32)maxw;
234 img->comps[1].h = (OPJ_UINT32)maxh;
235 img->comps[2].w = (OPJ_UINT32)maxw;
236 img->comps[2].h = (OPJ_UINT32)maxh;
237 img->comps[1].dx = img->comps[0].dx;
238 img->comps[2].dx = img->comps[0].dx;
239 img->comps[1].dy = img->comps[0].dy;
240 img->comps[2].dy = img->comps[0].dy;
241 }
sycc420_to_rgb(opj_image_t * img)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 }
color_sycc_to_rgb(opj_image_t * img)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 }
color_apply_icc_profile(opj_image_t * image)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_memset8(image->comps[1].data, 0, sizeof(int) * (size_t)max);
476 image->comps[2].data = FX_Alloc(int, (size_t)max);
477 FXSYS_memset8(image->comps[2].data, 0, sizeof(int) * (size_t)max);
478 image->numcomps += 2;
479 r = image->comps[0].data;
480 for(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 }
color_apply_conversion(opj_image_t * image)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(FX_LPBYTE dest_buf, int pitch, FX_BOOL bTranslateColor, FX_LPBYTE offsets);
593 FX_LPCBYTE 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 };
CJPX_Decoder()600 CJPX_Decoder::CJPX_Decoder(): image(NULL), l_codec(NULL), l_stream(NULL), m_useColorSpace(FALSE)
601 {
602 }
~CJPX_Decoder()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 }
Init(const unsigned char * src_data,int src_size)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, 0x50, 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_memcmp32(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 /*
653 if(this->m_useColorSpace) {
654 image->useColorSpace = 1;
655 } else {
656 image->useColorSpace = 0;
657 }
658 */
659 if (!parameters.nb_tile_to_decode) {
660 if (!opj_set_decode_area(l_codec, image, parameters.DA_x0,
661 parameters.DA_y0, parameters.DA_x1, parameters.DA_y1)) {
662 opj_image_destroy(image);
663 image = NULL;
664 return FALSE;
665 }
666 if (!(opj_decode(l_codec, l_stream, image) && opj_end_decompress(l_codec, l_stream))) {
667 opj_image_destroy(image);
668 image = NULL;
669 return FALSE;
670 }
671 } else {
672 if (!opj_get_decoded_tile(l_codec, l_stream, image, parameters.tile_index)) {
673 return FALSE;
674 }
675 }
676 opj_stream_destroy(l_stream);
677 l_stream = NULL;
678 if( image->color_space != OPJ_CLRSPC_SYCC
679 && image->numcomps == 3 && image->comps[0].dx == image->comps[0].dy
680 && image->comps[1].dx != 1 ) {
681 image->color_space = OPJ_CLRSPC_SYCC;
682 } else if (image->numcomps <= 2) {
683 image->color_space = OPJ_CLRSPC_GRAY;
684 }
685 if(image->color_space == OPJ_CLRSPC_SYCC) {
686 color_sycc_to_rgb(image);
687 }
688 //if(image->icc_profile_buf && !image->useColorSpace) {
689 if(image->icc_profile_buf) {
690 FX_Free(image->icc_profile_buf);
691 image->icc_profile_buf = NULL;
692 image->icc_profile_len = 0;
693 }
694 if(!image) {
695 return FALSE;
696 }
697 return TRUE;
698 }
GetInfo(FX_DWORD & width,FX_DWORD & height,FX_DWORD & codestream_nComps,FX_DWORD & output_nComps)699 void CJPX_Decoder::GetInfo(FX_DWORD& width, FX_DWORD& height, FX_DWORD& codestream_nComps, FX_DWORD& output_nComps)
700 {
701 width = (FX_DWORD)image->x1;
702 height = (FX_DWORD)image->y1;
703 output_nComps = codestream_nComps = (FX_DWORD)image->numcomps;
704 }
Decode(FX_LPBYTE dest_buf,int pitch,FX_BOOL bTranslateColor,FX_LPBYTE offsets)705 FX_BOOL CJPX_Decoder::Decode(FX_LPBYTE dest_buf, int pitch, FX_BOOL bTranslateColor, FX_LPBYTE offsets)
706 {
707 int i, wid, hei, row, col, channel, src;
708 FX_LPBYTE pChannel, pScanline, pPixel;
709
710 if(image->comps[0].w != image->x1 || image->comps[0].h != image->y1) {
711 return FALSE;
712 }
713 if(pitch < (int)(image->comps[0].w * 8 * image->numcomps + 31) >> 5 << 2) {
714 return FALSE;
715 }
716 FXSYS_memset8(dest_buf, 0xff, image->y1 * pitch);
717 FX_BYTE** channel_bufs = FX_Alloc(FX_BYTE*, image->numcomps);
718 FX_BOOL result = FALSE;
719 int* adjust_comps = FX_Alloc(int, image->numcomps);
720 for (i = 0; i < (int)image->numcomps; i ++) {
721 channel_bufs[i] = dest_buf + offsets[i];
722 adjust_comps[i] = image->comps[i].prec - 8;
723 if(i > 0) {
724 if(image->comps[i].dx != image->comps[i - 1].dx
725 || image->comps[i].dy != image->comps[i - 1].dy
726 || image->comps[i].prec != image->comps[i - 1].prec) {
727 goto done;
728 }
729 }
730 }
731 wid = image->comps[0].w;
732 hei = image->comps[0].h;
733 for (channel = 0; channel < (int)image->numcomps; channel++) {
734 pChannel = channel_bufs[channel];
735 if(adjust_comps[channel] < 0) {
736 for(row = 0; row < hei; row++) {
737 pScanline = pChannel + row * pitch;
738 for (col = 0; col < wid; col++) {
739 pPixel = pScanline + col * image->numcomps;
740 src = image->comps[channel].data[row * wid + col];
741 src += image->comps[channel].sgnd ? 1 << (image->comps[channel].prec - 1) : 0;
742 if (adjust_comps[channel] > 0) {
743 *pPixel = 0;
744 } else {
745 *pPixel = (FX_BYTE)(src << -adjust_comps[channel]);
746 }
747 }
748 }
749 } else {
750 for(row = 0; row < hei; row++) {
751 pScanline = pChannel + row * pitch;
752 for (col = 0; col < wid; col++) {
753 pPixel = pScanline + col * image->numcomps;
754 if (!image->comps[channel].data) {
755 continue;
756 }
757 src = image->comps[channel].data[row * wid + col];
758 src += image->comps[channel].sgnd ? 1 << (image->comps[channel].prec - 1) : 0;
759 if (adjust_comps[channel] - 1 < 0) {
760 *pPixel = (FX_BYTE)((src >> adjust_comps[channel]));
761 } else {
762 int tmpPixel = (src >> adjust_comps[channel]) + ((src >> (adjust_comps[channel] - 1)) % 2);
763 if (tmpPixel > 255) {
764 tmpPixel = 255;
765 } else if (tmpPixel < 0) {
766 tmpPixel = 0;
767 }
768 *pPixel = (FX_BYTE)tmpPixel;
769 }
770 }
771 }
772 }
773 }
774 result = TRUE;
775
776 done:
777 FX_Free(channel_bufs);
778 FX_Free(adjust_comps);
779 return result;
780 }
781 void initialize_transition_table();
782 void initialize_significance_luts();
783 void initialize_sign_lut();
CCodec_JpxModule()784 CCodec_JpxModule::CCodec_JpxModule()
785 {
786 }
CreateDecoder(FX_LPCBYTE src_buf,FX_DWORD src_size,FX_BOOL useColorSpace)787 void* CCodec_JpxModule::CreateDecoder(FX_LPCBYTE src_buf, FX_DWORD src_size , FX_BOOL useColorSpace)
788 {
789 CJPX_Decoder* pDecoder = new CJPX_Decoder;
790 pDecoder->m_useColorSpace = useColorSpace;
791 if (!pDecoder->Init(src_buf, src_size)) {
792 delete pDecoder;
793 return NULL;
794 }
795 return pDecoder;
796 }
GetImageInfo(FX_LPVOID ctx,FX_DWORD & width,FX_DWORD & height,FX_DWORD & codestream_nComps,FX_DWORD & output_nComps)797 void CCodec_JpxModule::GetImageInfo(FX_LPVOID ctx, FX_DWORD& width, FX_DWORD& height,
798 FX_DWORD& codestream_nComps, FX_DWORD& output_nComps)
799 {
800 CJPX_Decoder* pDecoder = (CJPX_Decoder*)ctx;
801 pDecoder->GetInfo(width, height, codestream_nComps, output_nComps);
802 }
Decode(void * ctx,FX_LPBYTE dest_data,int pitch,FX_BOOL bTranslateColor,FX_LPBYTE offsets)803 FX_BOOL CCodec_JpxModule::Decode(void* ctx, FX_LPBYTE dest_data, int pitch, FX_BOOL bTranslateColor, FX_LPBYTE offsets)
804 {
805 CJPX_Decoder* pDecoder = (CJPX_Decoder*)ctx;
806 return pDecoder->Decode(dest_data, pitch, bTranslateColor, offsets);
807 }
DestroyDecoder(void * ctx)808 void CCodec_JpxModule::DestroyDecoder(void* ctx)
809 {
810 CJPX_Decoder* pDecoder = (CJPX_Decoder*)ctx;
811 delete pDecoder;
812 }
813