2 * Copyright (c) 2002-2007, Communications and Remote Sensing Laboratory, Universite catholique de Louvain (UCL), Belgium
3 * Copyright (c) 2002-2007, Professor Benoit Macq
4 * Copyright (c) 2001-2003, David Janssens
5 * Copyright (c) 2002-2003, Yannick Verschueren
6 * Copyright (c) 2003-2007, Francois-Olivier Devaux and Antonin Descampe
7 * Copyright (c) 2005, Herve Drolon, FreeImage Team
10 * Redistribution and use in source and binary forms, with or without
11 * modification, are permitted provided that the following conditions
13 * 1. Redistributions of source code must retain the above copyright
14 * notice, this list of conditions and the following disclaimer.
15 * 2. Redistributions in binary form must reproduce the above copyright
16 * notice, this list of conditions and the following disclaimer in the
17 * documentation and/or other materials provided with the distribution.
19 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS `AS IS'
20 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
21 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
22 * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
23 * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
24 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
25 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
26 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
27 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
28 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
29 * POSSIBILITY OF SUCH DAMAGE.
38 #include "opj_apps_config.h"
42 #ifdef OPJ_HAVE_LIBLCMS2
45 #ifdef OPJ_HAVE_LIBLCMS1
50 #define OPJ_CLRSPC_GRAY CLRSPC_GRAY
51 #define OPJ_CLRSPC_SRGB CLRSPC_SRGB
54 /*--------------------------------------------------------
55 Matrix for sYCC, Amendment 1 to IEC 61966-2-1
57 Y : 0.299 0.587 0.114 :R
58 Cb: -0.1687 -0.3312 0.5 :G
59 Cr: 0.5 -0.4187 -0.0812 :B
63 R: 1 -3.68213e-05 1.40199 :Y
64 G: 1.00003 -0.344125 -0.714128 :Cb - 2^(prec - 1)
65 B: 0.999823 1.77204 -8.04142e-06 :Cr - 2^(prec - 1)
67 -----------------------------------------------------------*/
68 static void sycc_to_rgb(int offset, int upb, int y, int cb, int cr,
69 int *out_r, int *out_g, int *out_b)
73 cb -= offset; cr -= offset;
74 r = y + (int)(1.402 * (float)cr);
75 if(r < 0) r = 0; else if(r > upb) r = upb; *out_r = r;
77 g = y - (int)(0.344 * (float)cb + 0.714 * (float)cr);
78 if(g < 0) g = 0; else if(g > upb) g = upb; *out_g = g;
80 b = y + (int)(1.772 * (float)cb);
81 if(b < 0) b = 0; else if(b > upb) b = upb; *out_b = b;
84 static void sycc444_to_rgb(opj_image_t *img)
86 int *d0, *d1, *d2, *r, *g, *b;
87 const int *y, *cb, *cr;
88 int maxw, maxh, max, i, offset, upb;
90 i = (int)img->comps[0].prec;
91 offset = 1<<(i - 1); upb = (1<<i)-1;
93 maxw = (int)img->comps[0].w; maxh = (int)img->comps[0].h;
96 y = img->comps[0].data;
97 cb = img->comps[1].data;
98 cr = img->comps[2].data;
100 d0 = r = (int*)malloc(sizeof(int) * (size_t)max);
101 d1 = g = (int*)malloc(sizeof(int) * (size_t)max);
102 d2 = b = (int*)malloc(sizeof(int) * (size_t)max);
104 for(i = 0; i < max; ++i)
106 sycc_to_rgb(offset, upb, *y, *cb, *cr, r, g, b);
108 ++y; ++cb; ++cr; ++r; ++g; ++b;
110 free(img->comps[0].data); img->comps[0].data = d0;
111 free(img->comps[1].data); img->comps[1].data = d1;
112 free(img->comps[2].data); img->comps[2].data = d2;
114 }/* sycc444_to_rgb() */
116 static void sycc422_to_rgb(opj_image_t *img)
118 int *d0, *d1, *d2, *r, *g, *b;
119 const int *y, *cb, *cr;
120 int maxw, maxh, max, offset, upb;
123 i = (int)img->comps[0].prec;
124 offset = 1<<(i - 1); upb = (1<<i)-1;
126 maxw = (int)img->comps[0].w; maxh = (int)img->comps[0].h;
129 y = img->comps[0].data;
130 cb = img->comps[1].data;
131 cr = img->comps[2].data;
133 d0 = r = (int*)malloc(sizeof(int) * (size_t)max);
134 d1 = g = (int*)malloc(sizeof(int) * (size_t)max);
135 d2 = b = (int*)malloc(sizeof(int) * (size_t)max);
137 for(i=0; i < maxh; ++i)
139 for(j=0; j < maxw; j += 2)
141 sycc_to_rgb(offset, upb, *y, *cb, *cr, r, g, b);
145 sycc_to_rgb(offset, upb, *y, *cb, *cr, r, g, b);
147 ++y; ++r; ++g; ++b; ++cb; ++cr;
150 free(img->comps[0].data); img->comps[0].data = d0;
151 free(img->comps[1].data); img->comps[1].data = d1;
152 free(img->comps[2].data); img->comps[2].data = d2;
154 #if defined(USE_JPWL) || defined(USE_MJ2)
155 img->comps[1].w = maxw; img->comps[1].h = maxh;
156 img->comps[2].w = maxw; img->comps[2].h = maxh;
158 img->comps[1].w = (OPJ_UINT32)maxw; img->comps[1].h = (OPJ_UINT32)maxh;
159 img->comps[2].w = (OPJ_UINT32)maxw; img->comps[2].h = (OPJ_UINT32)maxh;
161 img->comps[1].dx = img->comps[0].dx;
162 img->comps[2].dx = img->comps[0].dx;
163 img->comps[1].dy = img->comps[0].dy;
164 img->comps[2].dy = img->comps[0].dy;
166 }/* sycc422_to_rgb() */
168 static void sycc420_to_rgb(opj_image_t *img)
170 int *d0, *d1, *d2, *r, *g, *b, *nr, *ng, *nb;
171 const int *y, *cb, *cr, *ny;
172 int maxw, maxh, max, offset, upb;
175 i = (int)img->comps[0].prec;
176 offset = 1<<(i - 1); upb = (1<<i)-1;
178 maxw = (int)img->comps[0].w; maxh = (int)img->comps[0].h;
181 y = img->comps[0].data;
182 cb = img->comps[1].data;
183 cr = img->comps[2].data;
185 d0 = r = (int*)malloc(sizeof(int) * (size_t)max);
186 d1 = g = (int*)malloc(sizeof(int) * (size_t)max);
187 d2 = b = (int*)malloc(sizeof(int) * (size_t)max);
189 for(i=0; i < maxh; i += 2)
192 nr = r + maxw; ng = g + maxw; nb = b + maxw;
194 for(j=0; j < maxw; j += 2)
196 sycc_to_rgb(offset, upb, *y, *cb, *cr, r, g, b);
200 sycc_to_rgb(offset, upb, *y, *cb, *cr, r, g, b);
204 sycc_to_rgb(offset, upb, *ny, *cb, *cr, nr, ng, nb);
206 ++ny; ++nr; ++ng; ++nb;
208 sycc_to_rgb(offset, upb, *ny, *cb, *cr, nr, ng, nb);
210 ++ny; ++nr; ++ng; ++nb; ++cb; ++cr;
212 y += maxw; r += maxw; g += maxw; b += maxw;
214 free(img->comps[0].data); img->comps[0].data = d0;
215 free(img->comps[1].data); img->comps[1].data = d1;
216 free(img->comps[2].data); img->comps[2].data = d2;
218 #if defined(USE_JPWL) || defined(USE_MJ2)
219 img->comps[1].w = maxw; img->comps[1].h = maxh;
220 img->comps[2].w = maxw; img->comps[2].h = maxh;
222 img->comps[1].w = (OPJ_UINT32)maxw; img->comps[1].h = (OPJ_UINT32)maxh;
223 img->comps[2].w = (OPJ_UINT32)maxw; img->comps[2].h = (OPJ_UINT32)maxh;
225 img->comps[1].dx = img->comps[0].dx;
226 img->comps[2].dx = img->comps[0].dx;
227 img->comps[1].dy = img->comps[0].dy;
228 img->comps[2].dy = img->comps[0].dy;
230 }/* sycc420_to_rgb() */
232 void color_sycc_to_rgb(opj_image_t *img)
234 if(img->numcomps < 3)
236 img->color_space = OPJ_CLRSPC_GRAY;
240 if((img->comps[0].dx == 1)
241 && (img->comps[1].dx == 2)
242 && (img->comps[2].dx == 2)
243 && (img->comps[0].dy == 1)
244 && (img->comps[1].dy == 2)
245 && (img->comps[2].dy == 2))/* horizontal and vertical sub-sample */
250 if((img->comps[0].dx == 1)
251 && (img->comps[1].dx == 2)
252 && (img->comps[2].dx == 2)
253 && (img->comps[0].dy == 1)
254 && (img->comps[1].dy == 1)
255 && (img->comps[2].dy == 1))/* horizontal sub-sample only */
260 if((img->comps[0].dx == 1)
261 && (img->comps[1].dx == 1)
262 && (img->comps[2].dx == 1)
263 && (img->comps[0].dy == 1)
264 && (img->comps[1].dy == 1)
265 && (img->comps[2].dy == 1))/* no sub-sample */
271 fprintf(stderr,"%s:%d:color_sycc_to_rgb\n\tCAN NOT CONVERT\n",
275 img->color_space = OPJ_CLRSPC_SRGB;
277 }/* color_sycc_to_rgb() */
279 #if defined(OPJ_HAVE_LIBLCMS2) || defined(OPJ_HAVE_LIBLCMS1)
280 #ifdef OPJ_HAVE_LIBLCMS1
281 /* Bob Friesenhahn proposed:*/
282 #define cmsSigXYZData icSigXYZData
283 #define cmsSigLabData icSigLabData
284 #define cmsSigCmykData icSigCmykData
285 #define cmsSigYCbCrData icSigYCbCrData
286 #define cmsSigLuvData icSigLuvData
287 #define cmsSigGrayData icSigGrayData
288 #define cmsSigRgbData icSigRgbData
289 #define cmsUInt32Number DWORD
291 #define cmsColorSpaceSignature icColorSpaceSignature
292 #define cmsGetHeaderRenderingIntent cmsTakeRenderingIntent
294 #endif /* OPJ_HAVE_LIBLCMS1 */
296 /*#define DEBUG_PROFILE*/
297 void color_apply_icc_profile(opj_image_t *image)
299 cmsHPROFILE in_prof, out_prof;
300 cmsHTRANSFORM transform;
301 cmsColorSpaceSignature in_space, out_space;
302 cmsUInt32Number intent, in_type, out_type, nr_samples;
304 int prec, i, max, max_w, max_h;
305 OPJ_COLOR_SPACE oldspace;
308 cmsOpenProfileFromMem(image->icc_profile_buf, image->icc_profile_len);
310 FILE *icm = fopen("debug.icm","wb");
311 fwrite( image->icc_profile_buf,1, image->icc_profile_len,icm);
315 if(in_prof == NULL) return;
317 in_space = cmsGetPCS(in_prof);
318 out_space = cmsGetColorSpace(in_prof);
319 intent = cmsGetHeaderRenderingIntent(in_prof);
322 max_w = (int)image->comps[0].w;
323 max_h = (int)image->comps[0].h;
324 prec = (int)image->comps[0].prec;
325 oldspace = image->color_space;
327 if(out_space == cmsSigRgbData) /* enumCS 16 */
331 in_type = TYPE_RGB_8;
332 out_type = TYPE_RGB_8;
336 in_type = TYPE_RGB_16;
337 out_type = TYPE_RGB_16;
339 out_prof = cmsCreate_sRGBProfile();
340 image->color_space = OPJ_CLRSPC_SRGB;
343 if(out_space == cmsSigGrayData) /* enumCS 17 */
345 in_type = TYPE_GRAY_8;
346 out_type = TYPE_RGB_8;
347 out_prof = cmsCreate_sRGBProfile();
348 image->color_space = OPJ_CLRSPC_SRGB;
351 if(out_space == cmsSigYCbCrData) /* enumCS 18 */
353 in_type = TYPE_YCbCr_16;
354 out_type = TYPE_RGB_16;
355 out_prof = cmsCreate_sRGBProfile();
356 image->color_space = OPJ_CLRSPC_SRGB;
361 fprintf(stderr,"%s:%d: color_apply_icc_profile\n\tICC Profile has unknown "
362 "output colorspace(%#x)(%c%c%c%c)\n\tICC Profile ignored.\n",
363 __FILE__,__LINE__,out_space,
364 (out_space>>24) & 0xff,(out_space>>16) & 0xff,
365 (out_space>>8) & 0xff, out_space & 0xff);
371 fprintf(stderr,"%s:%d:color_apply_icc_profile\n\tchannels(%d) prec(%d) w(%d) h(%d)"
372 "\n\tprofile: in(%p) out(%p)\n",__FILE__,__LINE__,image->numcomps,prec,
373 max_w,max_h, (void*)in_prof,(void*)out_prof);
375 fprintf(stderr,"\trender_intent (%u)\n\t"
376 "color_space: in(%#x)(%c%c%c%c) out:(%#x)(%c%c%c%c)\n\t"
377 " type: in(%u) out:(%u)\n",
380 (in_space>>24) & 0xff,(in_space>>16) & 0xff,
381 (in_space>>8) & 0xff, in_space & 0xff,
384 (out_space>>24) & 0xff,(out_space>>16) & 0xff,
385 (out_space>>8) & 0xff, out_space & 0xff,
392 #endif /* DEBUG_PROFILE */
394 transform = cmsCreateTransform(in_prof, in_type,
395 out_prof, out_type, intent, 0);
397 #ifdef OPJ_HAVE_LIBLCMS2
398 /* Possible for: LCMS_VERSION >= 2000 :*/
399 cmsCloseProfile(in_prof);
400 cmsCloseProfile(out_prof);
403 if(transform == NULL)
406 fprintf(stderr,"%s:%d:color_apply_icc_profile\n\tcmsCreateTransform failed. "
407 "ICC Profile ignored.\n",__FILE__,__LINE__);
409 image->color_space = oldspace;
410 #ifdef OPJ_HAVE_LIBLCMS1
411 cmsCloseProfile(in_prof);
412 cmsCloseProfile(out_prof);
417 if(image->numcomps > 2)/* RGB, RGBA */
421 unsigned char *inbuf, *outbuf, *in, *out;
423 nr_samples = (cmsUInt32Number)max * 3 * (cmsUInt32Number)sizeof(unsigned char);
424 in = inbuf = (unsigned char*)malloc(nr_samples);
425 out = outbuf = (unsigned char*)malloc(nr_samples);
427 r = image->comps[0].data;
428 g = image->comps[1].data;
429 b = image->comps[2].data;
431 for(i = 0; i < max; ++i)
433 *in++ = (unsigned char)*r++;
434 *in++ = (unsigned char)*g++;
435 *in++ = (unsigned char)*b++;
438 cmsDoTransform(transform, inbuf, outbuf, (cmsUInt32Number)max);
440 r = image->comps[0].data;
441 g = image->comps[1].data;
442 b = image->comps[2].data;
444 for(i = 0; i < max; ++i)
450 free(inbuf); free(outbuf);
454 unsigned short *inbuf, *outbuf, *in, *out;
456 nr_samples = (cmsUInt32Number)max * 3 * (cmsUInt32Number)sizeof(unsigned short);
457 in = inbuf = (unsigned short*)malloc(nr_samples);
458 out = outbuf = (unsigned short*)malloc(nr_samples);
460 r = image->comps[0].data;
461 g = image->comps[1].data;
462 b = image->comps[2].data;
464 for(i = 0; i < max; ++i)
466 *in++ = (unsigned short)*r++;
467 *in++ = (unsigned short)*g++;
468 *in++ = (unsigned short)*b++;
471 cmsDoTransform(transform, inbuf, outbuf, (cmsUInt32Number)max);
473 r = image->comps[0].data;
474 g = image->comps[1].data;
475 b = image->comps[2].data;
477 for(i = 0; i < max; ++i)
483 free(inbuf); free(outbuf);
486 else /* GRAY, GRAYA */
488 unsigned char *in, *inbuf, *out, *outbuf;
490 nr_samples = (cmsUInt32Number)max * 3 * sizeof(unsigned char);
491 in = inbuf = (unsigned char*)malloc(nr_samples);
492 out = outbuf = (unsigned char*)malloc(nr_samples);
494 image->comps = (opj_image_comp_t*)
495 realloc(image->comps, (image->numcomps+2)*sizeof(opj_image_comp_t));
497 if(image->numcomps == 2)
498 image->comps[3] = image->comps[1];
500 image->comps[1] = image->comps[0];
501 image->comps[2] = image->comps[0];
503 image->comps[1].data = (int*)calloc((size_t)max, sizeof(int));
504 image->comps[2].data = (int*)calloc((size_t)max, sizeof(int));
506 image->numcomps += 2;
508 r = image->comps[0].data;
510 for(i = 0; i < max; ++i)
512 *in++ = (unsigned char)*r++;
514 cmsDoTransform(transform, inbuf, outbuf, (cmsUInt32Number)max);
516 r = image->comps[0].data;
517 g = image->comps[1].data;
518 b = image->comps[2].data;
520 for(i = 0; i < max; ++i)
522 *r++ = (int)*out++; *g++ = (int)*out++; *b++ = (int)*out++;
524 free(inbuf); free(outbuf);
526 }/* if(image->numcomps */
528 cmsDeleteTransform(transform);
530 #ifdef OPJ_HAVE_LIBLCMS1
531 cmsCloseProfile(in_prof);
532 cmsCloseProfile(out_prof);
534 }/* color_apply_icc_profile() */
536 #endif /* OPJ_HAVE_LIBLCMS2 || OPJ_HAVE_LIBLCMS1 */