Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(1050)

Side by Side Diff: core/src/fxcodec/codec/fx_codec_jpx_opj.cpp

Issue 1265503005: clang-format all pdfium code. (Closed) Base URL: https://pdfium.googlesource.com/pdfium.git@master
Patch Set: sigh Created 5 years, 4 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
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(&parameters);
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, &parameters)) {
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(&parameters);
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, &parameters) ) {
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 }
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698