Engauge Digitizer 2
Loading...
Searching...
No Matches
Jpeg2000Color.cpp
1/*
2 * The copyright in this software is being made available under the 2-clauses
3 * BSD License, included below. This software may be subject to other third
4 * party and contributor rights, including patent rights, and no such rights
5 * are granted under this license.
6 *
7 * Copyright (c) 2002-2014, Universite catholique de Louvain (UCL), Belgium
8 * Copyright (c) 2002-2014, Professor Benoit Macq
9 * Copyright (c) 2001-2003, David Janssens
10 * Copyright (c) 2002-2003, Yannick Verschueren
11 * Copyright (c) 2003-2007, Francois-Olivier Devaux
12 * Copyright (c) 2003-2014, Antonin Descampe
13 * Copyright (c) 2005, Herve Drolon, FreeImage Team
14 * All rights reserved.
15 *
16 * Redistribution and use in source and binary forms, with or without
17 * modification, are permitted provided that the following conditions
18 * are met:
19 * 1. Redistributions of source code must retain the above copyright
20 * notice, this list of conditions and the following disclaimer.
21 * 2. Redistributions in binary form must reproduce the above copyright
22 * notice, this list of conditions and the following disclaimer in the
23 * documentation and/or other materials provided with the distribution.
24 *
25 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS `AS IS'
26 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
27 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
28 * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
29 * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
30 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
31 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
32 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
33 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
34 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
35 * POSSIBILITY OF SUCH DAMAGE.
36 */
37
38#include <stdio.h>
39#include <string.h>
40#include <stdlib.h>
41#include <math.h>
42#include <assert.h>
43
44#include "Jpeg2000Color.h"
45
46#ifdef OPJ_USE_LEGACY
47#define OPJ_CLRSPC_GRAY CLRSPC_GRAY
48#define OPJ_CLRSPC_SRGB CLRSPC_SRGB
49#endif
50
51/*--------------------------------------------------------
52 Matrix for sYCC, Amendment 1 to IEC 61966-2-1
53
54 Y : 0.299 0.587 0.114 :R
55 Cb: -0.1687 -0.3312 0.5 :G
56 Cr: 0.5 -0.4187 -0.0812 :B
57
58 Inverse:
59
60 R: 1 -3.68213e-05 1.40199 :Y
61 G: 1.00003 -0.344125 -0.714128 :Cb - 2^(prec - 1)
62 B: 0.999823 1.77204 -8.04142e-06 :Cr - 2^(prec - 1)
63
64 -----------------------------------------------------------*/
65void sycc_to_rgb(int offset, int upb, int y, int cb, int cr,
66 int *out_r, int *out_g, int *out_b)
67{
68 int r, g, b;
69
70 cb -= offset; cr -= offset;
71 r = y + (int)(1.402 * (float)cr);
72 if(r < 0) r = 0; else if(r > upb) r = upb; *out_r = r;
73
74 g = y - (int)(0.344 * (float)cb + 0.714 * (float)cr);
75 if(g < 0) g = 0; else if(g > upb) g = upb; *out_g = g;
76
77 b = y + (int)(1.772 * (float)cb);
78 if(b < 0) b = 0; else if(b > upb) b = upb; *out_b = b;
79}
80
81void sycc444_to_rgb(opj_image_t *img)
82{
83 int *d0, *d1, *d2, *r, *g, *b;
84 const int *y, *cb, *cr;
85 int maxw, maxh, max, i, offset, upb;
86
87 i = (int)img->comps[0].prec;
88 offset = 1<<(i - 1); upb = (1<<i)-1;
89
90 maxw = (int)img->comps[0].w; maxh = (int)img->comps[0].h;
91 max = maxw * maxh;
92
93 y = img->comps[0].data;
94 cb = img->comps[1].data;
95 cr = img->comps[2].data;
96
97 d0 = r = (int*)malloc(sizeof(int) * (size_t)max);
98 d1 = g = (int*)malloc(sizeof(int) * (size_t)max);
99 d2 = b = (int*)malloc(sizeof(int) * (size_t)max);
100
101 for(i = 0; i < max; ++i)
102 {
103 sycc_to_rgb(offset, upb, *y, *cb, *cr, r, g, b);
104
105 ++y; ++cb; ++cr; ++r; ++g; ++b;
106 }
107 free(img->comps[0].data); img->comps[0].data = d0;
108 free(img->comps[1].data); img->comps[1].data = d1;
109 free(img->comps[2].data); img->comps[2].data = d2;
110
111}/* sycc444_to_rgb() */
112
113void sycc422_to_rgb(opj_image_t *img)
114{
115 int *d0, *d1, *d2, *r, *g, *b;
116 const int *y, *cb, *cr;
117 int maxw, maxh, max, offset, upb;
118 int i, j;
119
120 i = (int)img->comps[0].prec;
121 offset = 1<<(i - 1); upb = (1<<i)-1;
122
123 maxw = (int)img->comps[0].w; maxh = (int)img->comps[0].h;
124 max = maxw * maxh;
125
126 y = img->comps[0].data;
127 cb = img->comps[1].data;
128 cr = img->comps[2].data;
129
130 d0 = r = (int*)malloc(sizeof(int) * (size_t)max);
131 d1 = g = (int*)malloc(sizeof(int) * (size_t)max);
132 d2 = b = (int*)malloc(sizeof(int) * (size_t)max);
133
134 for(i=0; i < maxh; ++i)
135 {
136 for(j=0; j < maxw; j += 2)
137 {
138 sycc_to_rgb(offset, upb, *y, *cb, *cr, r, g, b);
139
140 ++y; ++r; ++g; ++b;
141
142 sycc_to_rgb(offset, upb, *y, *cb, *cr, r, g, b);
143
144 ++y; ++r; ++g; ++b; ++cb; ++cr;
145 }
146 }
147 free(img->comps[0].data); img->comps[0].data = d0;
148 free(img->comps[1].data); img->comps[1].data = d1;
149 free(img->comps[2].data); img->comps[2].data = d2;
150
151#if defined(USE_JPWL) || defined(USE_MJ2)
152 img->comps[1].w = maxw; img->comps[1].h = maxh;
153 img->comps[2].w = maxw; img->comps[2].h = maxh;
154#else
155 img->comps[1].w = (OPJ_UINT32)maxw; img->comps[1].h = (OPJ_UINT32)maxh;
156 img->comps[2].w = (OPJ_UINT32)maxw; img->comps[2].h = (OPJ_UINT32)maxh;
157#endif
158 img->comps[1].dx = img->comps[0].dx;
159 img->comps[2].dx = img->comps[0].dx;
160 img->comps[1].dy = img->comps[0].dy;
161 img->comps[2].dy = img->comps[0].dy;
162
163}/* sycc422_to_rgb() */
164
165void sycc420_to_rgb(opj_image_t *img)
166{
167 int *d0, *d1, *d2, *r, *g, *b, *nr, *ng, *nb;
168 const int *y, *cb, *cr, *ny;
169 int maxw, maxh, max, offset, upb;
170 int i, j;
171
172 i = (int)img->comps[0].prec;
173 offset = 1<<(i - 1); upb = (1<<i)-1;
174
175 maxw = (int)img->comps[0].w; maxh = (int)img->comps[0].h;
176 max = maxw * maxh;
177
178 y = img->comps[0].data;
179 cb = img->comps[1].data;
180 cr = img->comps[2].data;
181
182 d0 = r = (int*)malloc(sizeof(int) * (size_t)max);
183 d1 = g = (int*)malloc(sizeof(int) * (size_t)max);
184 d2 = b = (int*)malloc(sizeof(int) * (size_t)max);
185
186 for(i=0; i < maxh; i += 2)
187 {
188 ny = y + maxw;
189 nr = r + maxw; ng = g + maxw; nb = b + maxw;
190
191 for(j=0; j < maxw; j += 2)
192 {
193 sycc_to_rgb(offset, upb, *y, *cb, *cr, r, g, b);
194
195 ++y; ++r; ++g; ++b;
196
197 sycc_to_rgb(offset, upb, *y, *cb, *cr, r, g, b);
198
199 ++y; ++r; ++g; ++b;
200
201 sycc_to_rgb(offset, upb, *ny, *cb, *cr, nr, ng, nb);
202
203 ++ny; ++nr; ++ng; ++nb;
204
205 sycc_to_rgb(offset, upb, *ny, *cb, *cr, nr, ng, nb);
206
207 ++ny; ++nr; ++ng; ++nb; ++cb; ++cr;
208 }
209 y += maxw; r += maxw; g += maxw; b += maxw;
210 }
211 free(img->comps[0].data); img->comps[0].data = d0;
212 free(img->comps[1].data); img->comps[1].data = d1;
213 free(img->comps[2].data); img->comps[2].data = d2;
214
215#if defined(USE_JPWL) || defined(USE_MJ2)
216 img->comps[1].w = maxw; img->comps[1].h = maxh;
217 img->comps[2].w = maxw; img->comps[2].h = maxh;
218#else
219 img->comps[1].w = (OPJ_UINT32)maxw; img->comps[1].h = (OPJ_UINT32)maxh;
220 img->comps[2].w = (OPJ_UINT32)maxw; img->comps[2].h = (OPJ_UINT32)maxh;
221#endif
222 img->comps[1].dx = img->comps[0].dx;
223 img->comps[2].dx = img->comps[0].dx;
224 img->comps[1].dy = img->comps[0].dy;
225 img->comps[2].dy = img->comps[0].dy;
226
227}/* sycc420_to_rgb() */
228
229void color_sycc_to_rgb(opj_image_t *img)
230{
231 if(img->numcomps < 3)
232 {
233 img->color_space = OPJ_CLRSPC_GRAY;
234 return;
235 }
236
237 if((img->comps[0].dx == 1)
238 && (img->comps[1].dx == 2)
239 && (img->comps[2].dx == 2)
240 && (img->comps[0].dy == 1)
241 && (img->comps[1].dy == 2)
242 && (img->comps[2].dy == 2))/* horizontal and vertical sub-sample */
243 {
244 sycc420_to_rgb(img);
245 }
246 else {
247 if((img->comps[0].dx == 1)
248 && (img->comps[1].dx == 2)
249 && (img->comps[2].dx == 2)
250 && (img->comps[0].dy == 1)
251 && (img->comps[1].dy == 1)
252 && (img->comps[2].dy == 1))/* horizontal sub-sample only */
253 {
254 sycc422_to_rgb(img);
255 }
256 else {
257 if((img->comps[0].dx == 1)
258 && (img->comps[1].dx == 1)
259 && (img->comps[2].dx == 1)
260 && (img->comps[0].dy == 1)
261 && (img->comps[1].dy == 1)
262 && (img->comps[2].dy == 1))/* no sub-sample */
263 {
264 sycc444_to_rgb(img);
265 }
266 else
267 {
268 fprintf(stderr,"%s:%d:color_sycc_to_rgb\n\tCAN NOT CONVERT\n",
269 __FILE__,__LINE__);
270 return;
271 }
272 }
273 }
274 img->color_space = OPJ_CLRSPC_SRGB;
275}/* color_sycc_to_rgb() */
276
277#if defined(OPJ_HAVE_LIBLCMS2) || defined(OPJ_HAVE_LIBLCMS1)
278#ifdef OPJ_HAVE_LIBLCMS1
279/* Bob Friesenhahn proposed:*/
280#define cmsSigXYZData icSigXYZData
281#define cmsSigLabData icSigLabData
282#define cmsSigCmykData icSigCmykData
283#define cmsSigYCbCrData icSigYCbCrData
284#define cmsSigLuvData icSigLuvData
285#define cmsSigGrayData icSigGrayData
286#define cmsSigRgbData icSigRgbData
287#define cmsUInt32Number DWORD
288
289#define cmsColorSpaceSignature icColorSpaceSignature
290#define cmsGetHeaderRenderingIntent cmsTakeRenderingIntent
291
292#endif /* OPJ_HAVE_LIBLCMS1 */
293
294void color_apply_icc_profile(opj_image_t *image)
295{
296 cmsHPROFILE in_prof, out_prof;
297 cmsHTRANSFORM transform;
298 cmsColorSpaceSignature in_space, out_space;
299 cmsUInt32Number intent, in_type, out_type, nr_samples;
300 int *r, *g, *b;
301 int prec, i, max, max_w, max_h;
302 OPJ_COLOR_SPACE oldspace;
303
304 in_prof =
305 cmsOpenProfileFromMem(image->icc_profile_buf, image->icc_profile_len);
306
307 if(in_prof == NULL) return;
308
309 in_space = cmsGetPCS(in_prof);
310 out_space = cmsGetColorSpace(in_prof);
311 intent = cmsGetHeaderRenderingIntent(in_prof);
312
313
314 max_w = (int)image->comps[0].w;
315 max_h = (int)image->comps[0].h;
316 prec = (int)image->comps[0].prec;
317 oldspace = image->color_space;
318
319 if(out_space == cmsSigRgbData) /* enumCS 16 */
320 {
321 if( prec <= 8 )
322 {
323 in_type = TYPE_RGB_8;
324 out_type = TYPE_RGB_8;
325 }
326 else
327 {
328 in_type = TYPE_RGB_16;
329 out_type = TYPE_RGB_16;
330 }
331 out_prof = cmsCreate_sRGBProfile();
332 image->color_space = OPJ_CLRSPC_SRGB;
333 }
334 else
335 if(out_space == cmsSigGrayData) /* enumCS 17 */
336 {
337 in_type = TYPE_GRAY_8;
338 out_type = TYPE_RGB_8;
339 out_prof = cmsCreate_sRGBProfile();
340 image->color_space = OPJ_CLRSPC_SRGB;
341 }
342 else
343 if(out_space == cmsSigYCbCrData) /* enumCS 18 */
344 {
345 in_type = TYPE_YCbCr_16;
346 out_type = TYPE_RGB_16;
347 out_prof = cmsCreate_sRGBProfile();
348 image->color_space = OPJ_CLRSPC_SRGB;
349 }
350 else
351 {
352 return;
353 }
354
355 (void)prec;
356 (void)in_space;
357
358 transform = cmsCreateTransform(in_prof, in_type,
359 out_prof, out_type, intent, 0);
360
361#ifdef OPJ_HAVE_LIBLCMS2
362 /* Possible for: LCMS_VERSION >= 2000 :*/
363 cmsCloseProfile(in_prof);
364 cmsCloseProfile(out_prof);
365#endif
366
367 if(transform == NULL)
368 {
369 image->color_space = oldspace;
370#ifdef OPJ_HAVE_LIBLCMS1
371 cmsCloseProfile(in_prof);
372 cmsCloseProfile(out_prof);
373#endif
374 return;
375 }
376
377 if(image->numcomps > 2)/* RGB, RGBA */
378 {
379 if( prec <= 8 )
380 {
381 unsigned char *inbuf, *outbuf, *in, *out;
382 max = max_w * max_h;
383 nr_samples = (cmsUInt32Number)max * 3 * (cmsUInt32Number)sizeof(unsigned char);
384 in = inbuf = (unsigned char*)malloc(nr_samples);
385 out = outbuf = (unsigned char*)malloc(nr_samples);
386
387 r = image->comps[0].data;
388 g = image->comps[1].data;
389 b = image->comps[2].data;
390
391 for(i = 0; i < max; ++i)
392 {
393 *in++ = (unsigned char)*r++;
394 *in++ = (unsigned char)*g++;
395 *in++ = (unsigned char)*b++;
396 }
397
398 cmsDoTransform(transform, inbuf, outbuf, (cmsUInt32Number)max);
399
400 r = image->comps[0].data;
401 g = image->comps[1].data;
402 b = image->comps[2].data;
403
404 for(i = 0; i < max; ++i)
405 {
406 *r++ = (int)*out++;
407 *g++ = (int)*out++;
408 *b++ = (int)*out++;
409 }
410 free(inbuf); free(outbuf);
411 }
412 else
413 {
414 unsigned short *inbuf, *outbuf, *in, *out;
415 max = max_w * max_h;
416 nr_samples = (cmsUInt32Number)max * 3 * (cmsUInt32Number)sizeof(unsigned short);
417 in = inbuf = (unsigned short*)malloc(nr_samples);
418 out = outbuf = (unsigned short*)malloc(nr_samples);
419
420 r = image->comps[0].data;
421 g = image->comps[1].data;
422 b = image->comps[2].data;
423
424 for(i = 0; i < max; ++i)
425 {
426 *in++ = (unsigned short)*r++;
427 *in++ = (unsigned short)*g++;
428 *in++ = (unsigned short)*b++;
429 }
430
431 cmsDoTransform(transform, inbuf, outbuf, (cmsUInt32Number)max);
432
433 r = image->comps[0].data;
434 g = image->comps[1].data;
435 b = image->comps[2].data;
436
437 for(i = 0; i < max; ++i)
438 {
439 *r++ = (int)*out++;
440 *g++ = (int)*out++;
441 *b++ = (int)*out++;
442 }
443 free(inbuf); free(outbuf);
444 }
445 }
446 else /* GRAY, GRAYA */
447 {
448 unsigned char *in, *inbuf, *out, *outbuf;
449 max = max_w * max_h;
450 nr_samples = (cmsUInt32Number)max * 3 * sizeof(unsigned char);
451 in = inbuf = (unsigned char*)malloc(nr_samples);
452 out = outbuf = (unsigned char*)malloc(nr_samples);
453
454 image->comps = (opj_image_comp_t*)
455 realloc(image->comps, (image->numcomps+2)*sizeof(opj_image_comp_t));
456
457 if(image->numcomps == 2)
458 image->comps[3] = image->comps[1];
459
460 image->comps[1] = image->comps[0];
461 image->comps[2] = image->comps[0];
462
463 image->comps[1].data = (int*)calloc((size_t)max, sizeof(int));
464 image->comps[2].data = (int*)calloc((size_t)max, sizeof(int));
465
466 image->numcomps += 2;
467
468 r = image->comps[0].data;
469
470 for(i = 0; i < max; ++i)
471 {
472 *in++ = (unsigned char)*r++;
473 }
474 cmsDoTransform(transform, inbuf, outbuf, (cmsUInt32Number)max);
475
476 r = image->comps[0].data;
477 g = image->comps[1].data;
478 b = image->comps[2].data;
479
480 for(i = 0; i < max; ++i)
481 {
482 *r++ = (int)*out++; *g++ = (int)*out++; *b++ = (int)*out++;
483 }
484 free(inbuf); free(outbuf);
485
486 }/* if(image->numcomps */
487
488 cmsDeleteTransform(transform);
489
490#ifdef OPJ_HAVE_LIBLCMS1
491 cmsCloseProfile(in_prof);
492 cmsCloseProfile(out_prof);
493#endif
494}/* color_apply_icc_profile() */
495
496#endif /* OPJ_HAVE_LIBLCMS2 || OPJ_HAVE_LIBLCMS1 */