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.
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.
16 * Redistribution and use in source and binary forms, with or without
17 * modification, are permitted provided that the following conditions
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.
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.
44 #include "opj_apps_config.h"
48 #ifdef OPJ_HAVE_LIBLCMS2
51 #ifdef OPJ_HAVE_LIBLCMS1
56 #define OPJ_CLRSPC_GRAY CLRSPC_GRAY
57 #define OPJ_CLRSPC_SRGB CLRSPC_SRGB
60 /*--------------------------------------------------------
61 Matrix for sYCC, Amendment 1 to IEC 61966-2-1
63 Y : 0.299 0.587 0.114 :R
64 Cb: -0.1687 -0.3312 0.5 :G
65 Cr: 0.5 -0.4187 -0.0812 :B
69 R: 1 -3.68213e-05 1.40199 :Y
70 G: 1.00003 -0.344125 -0.714128 :Cb - 2^(prec - 1)
71 B: 0.999823 1.77204 -8.04142e-06 :Cr - 2^(prec - 1)
73 -----------------------------------------------------------*/
74 static void sycc_to_rgb(int offset, int upb, int y, int cb, int cr,
75 int *out_r, int *out_g, int *out_b)
79 cb -= offset; cr -= offset;
80 r = y + (int)(1.402 * (float)cr);
81 if(r < 0) r = 0; else if(r > upb) r = upb; *out_r = r;
83 g = y - (int)(0.344 * (float)cb + 0.714 * (float)cr);
84 if(g < 0) g = 0; else if(g > upb) g = upb; *out_g = g;
86 b = y + (int)(1.772 * (float)cb);
87 if(b < 0) b = 0; else if(b > upb) b = upb; *out_b = b;
90 static void sycc444_to_rgb(opj_image_t *img)
92 int *d0, *d1, *d2, *r, *g, *b;
93 const int *y, *cb, *cr;
94 int maxw, maxh, max, i, offset, upb;
96 i = (int)img->comps[0].prec;
97 offset = 1<<(i - 1); upb = (1<<i)-1;
99 maxw = (int)img->comps[0].w; maxh = (int)img->comps[0].h;
102 y = img->comps[0].data;
103 cb = img->comps[1].data;
104 cr = img->comps[2].data;
106 d0 = r = (int*)malloc(sizeof(int) * (size_t)max);
107 d1 = g = (int*)malloc(sizeof(int) * (size_t)max);
108 d2 = b = (int*)malloc(sizeof(int) * (size_t)max);
110 for(i = 0; i < max; ++i)
112 sycc_to_rgb(offset, upb, *y, *cb, *cr, r, g, b);
114 ++y; ++cb; ++cr; ++r; ++g; ++b;
116 free(img->comps[0].data); img->comps[0].data = d0;
117 free(img->comps[1].data); img->comps[1].data = d1;
118 free(img->comps[2].data); img->comps[2].data = d2;
120 }/* sycc444_to_rgb() */
122 static void sycc422_to_rgb(opj_image_t *img)
124 int *d0, *d1, *d2, *r, *g, *b;
125 const int *y, *cb, *cr;
126 int maxw, maxh, max, offset, upb;
129 i = (int)img->comps[0].prec;
130 offset = 1<<(i - 1); upb = (1<<i)-1;
132 maxw = (int)img->comps[0].w; maxh = (int)img->comps[0].h;
135 y = img->comps[0].data;
136 cb = img->comps[1].data;
137 cr = img->comps[2].data;
139 d0 = r = (int*)malloc(sizeof(int) * (size_t)max);
140 d1 = g = (int*)malloc(sizeof(int) * (size_t)max);
141 d2 = b = (int*)malloc(sizeof(int) * (size_t)max);
143 for(i=0; i < maxh; ++i)
145 for(j=0; j < maxw; j += 2)
147 sycc_to_rgb(offset, upb, *y, *cb, *cr, r, g, b);
151 sycc_to_rgb(offset, upb, *y, *cb, *cr, r, g, b);
153 ++y; ++r; ++g; ++b; ++cb; ++cr;
156 free(img->comps[0].data); img->comps[0].data = d0;
157 free(img->comps[1].data); img->comps[1].data = d1;
158 free(img->comps[2].data); img->comps[2].data = d2;
160 #if defined(USE_JPWL) || defined(USE_MJ2)
161 img->comps[1].w = maxw; img->comps[1].h = maxh;
162 img->comps[2].w = maxw; img->comps[2].h = maxh;
164 img->comps[1].w = (OPJ_UINT32)maxw; img->comps[1].h = (OPJ_UINT32)maxh;
165 img->comps[2].w = (OPJ_UINT32)maxw; img->comps[2].h = (OPJ_UINT32)maxh;
167 img->comps[1].dx = img->comps[0].dx;
168 img->comps[2].dx = img->comps[0].dx;
169 img->comps[1].dy = img->comps[0].dy;
170 img->comps[2].dy = img->comps[0].dy;
172 }/* sycc422_to_rgb() */
174 static void sycc420_to_rgb(opj_image_t *img)
176 int *d0, *d1, *d2, *r, *g, *b, *nr, *ng, *nb;
177 const int *y, *cb, *cr, *ny;
178 int maxw, maxh, max, offset, upb;
181 i = (int)img->comps[0].prec;
182 offset = 1<<(i - 1); upb = (1<<i)-1;
184 maxw = (int)img->comps[0].w; maxh = (int)img->comps[0].h;
187 y = img->comps[0].data;
188 cb = img->comps[1].data;
189 cr = img->comps[2].data;
191 d0 = r = (int*)malloc(sizeof(int) * (size_t)max);
192 d1 = g = (int*)malloc(sizeof(int) * (size_t)max);
193 d2 = b = (int*)malloc(sizeof(int) * (size_t)max);
195 for(i=0; i < maxh; i += 2)
198 nr = r + maxw; ng = g + maxw; nb = b + maxw;
200 for(j=0; j < maxw; j += 2)
202 sycc_to_rgb(offset, upb, *y, *cb, *cr, r, g, b);
206 sycc_to_rgb(offset, upb, *y, *cb, *cr, r, g, b);
210 sycc_to_rgb(offset, upb, *ny, *cb, *cr, nr, ng, nb);
212 ++ny; ++nr; ++ng; ++nb;
214 sycc_to_rgb(offset, upb, *ny, *cb, *cr, nr, ng, nb);
216 ++ny; ++nr; ++ng; ++nb; ++cb; ++cr;
218 y += maxw; r += maxw; g += maxw; b += maxw;
220 free(img->comps[0].data); img->comps[0].data = d0;
221 free(img->comps[1].data); img->comps[1].data = d1;
222 free(img->comps[2].data); img->comps[2].data = d2;
224 #if defined(USE_JPWL) || defined(USE_MJ2)
225 img->comps[1].w = maxw; img->comps[1].h = maxh;
226 img->comps[2].w = maxw; img->comps[2].h = maxh;
228 img->comps[1].w = (OPJ_UINT32)maxw; img->comps[1].h = (OPJ_UINT32)maxh;
229 img->comps[2].w = (OPJ_UINT32)maxw; img->comps[2].h = (OPJ_UINT32)maxh;
231 img->comps[1].dx = img->comps[0].dx;
232 img->comps[2].dx = img->comps[0].dx;
233 img->comps[1].dy = img->comps[0].dy;
234 img->comps[2].dy = img->comps[0].dy;
236 }/* sycc420_to_rgb() */
238 void color_sycc_to_rgb(opj_image_t *img)
240 if(img->numcomps < 3)
242 img->color_space = OPJ_CLRSPC_GRAY;
246 if((img->comps[0].dx == 1)
247 && (img->comps[1].dx == 2)
248 && (img->comps[2].dx == 2)
249 && (img->comps[0].dy == 1)
250 && (img->comps[1].dy == 2)
251 && (img->comps[2].dy == 2))/* horizontal and vertical sub-sample */
256 if((img->comps[0].dx == 1)
257 && (img->comps[1].dx == 2)
258 && (img->comps[2].dx == 2)
259 && (img->comps[0].dy == 1)
260 && (img->comps[1].dy == 1)
261 && (img->comps[2].dy == 1))/* horizontal sub-sample only */
266 if((img->comps[0].dx == 1)
267 && (img->comps[1].dx == 1)
268 && (img->comps[2].dx == 1)
269 && (img->comps[0].dy == 1)
270 && (img->comps[1].dy == 1)
271 && (img->comps[2].dy == 1))/* no sub-sample */
277 fprintf(stderr,"%s:%d:color_sycc_to_rgb\n\tCAN NOT CONVERT\n",
281 img->color_space = OPJ_CLRSPC_SRGB;
283 }/* color_sycc_to_rgb() */
285 #if defined(OPJ_HAVE_LIBLCMS2) || defined(OPJ_HAVE_LIBLCMS1)
286 #ifdef OPJ_HAVE_LIBLCMS1
287 /* Bob Friesenhahn proposed:*/
288 #define cmsSigXYZData icSigXYZData
289 #define cmsSigLabData icSigLabData
290 #define cmsSigCmykData icSigCmykData
291 #define cmsSigYCbCrData icSigYCbCrData
292 #define cmsSigLuvData icSigLuvData
293 #define cmsSigGrayData icSigGrayData
294 #define cmsSigRgbData icSigRgbData
295 #define cmsUInt32Number DWORD
297 #define cmsColorSpaceSignature icColorSpaceSignature
298 #define cmsGetHeaderRenderingIntent cmsTakeRenderingIntent
300 #endif /* OPJ_HAVE_LIBLCMS1 */
302 /*#define DEBUG_PROFILE*/
303 void color_apply_icc_profile(opj_image_t *image)
305 cmsHPROFILE in_prof, out_prof;
306 cmsHTRANSFORM transform;
307 cmsColorSpaceSignature in_space, out_space;
308 cmsUInt32Number intent, in_type, out_type, nr_samples;
310 int prec, i, max, max_w, max_h;
311 OPJ_COLOR_SPACE oldspace;
314 cmsOpenProfileFromMem(image->icc_profile_buf, image->icc_profile_len);
316 FILE *icm = fopen("debug.icm","wb");
317 fwrite( image->icc_profile_buf,1, image->icc_profile_len,icm);
321 if(in_prof == NULL) return;
323 in_space = cmsGetPCS(in_prof);
324 out_space = cmsGetColorSpace(in_prof);
325 intent = cmsGetHeaderRenderingIntent(in_prof);
328 max_w = (int)image->comps[0].w;
329 max_h = (int)image->comps[0].h;
330 prec = (int)image->comps[0].prec;
331 oldspace = image->color_space;
333 if(out_space == cmsSigRgbData) /* enumCS 16 */
337 in_type = TYPE_RGB_8;
338 out_type = TYPE_RGB_8;
342 in_type = TYPE_RGB_16;
343 out_type = TYPE_RGB_16;
345 out_prof = cmsCreate_sRGBProfile();
346 image->color_space = OPJ_CLRSPC_SRGB;
349 if(out_space == cmsSigGrayData) /* enumCS 17 */
351 in_type = TYPE_GRAY_8;
352 out_type = TYPE_RGB_8;
353 out_prof = cmsCreate_sRGBProfile();
354 image->color_space = OPJ_CLRSPC_SRGB;
357 if(out_space == cmsSigYCbCrData) /* enumCS 18 */
359 in_type = TYPE_YCbCr_16;
360 out_type = TYPE_RGB_16;
361 out_prof = cmsCreate_sRGBProfile();
362 image->color_space = OPJ_CLRSPC_SRGB;
367 fprintf(stderr,"%s:%d: color_apply_icc_profile\n\tICC Profile has unknown "
368 "output colorspace(%#x)(%c%c%c%c)\n\tICC Profile ignored.\n",
369 __FILE__,__LINE__,out_space,
370 (out_space>>24) & 0xff,(out_space>>16) & 0xff,
371 (out_space>>8) & 0xff, out_space & 0xff);
377 fprintf(stderr,"%s:%d:color_apply_icc_profile\n\tchannels(%d) prec(%d) w(%d) h(%d)"
378 "\n\tprofile: in(%p) out(%p)\n",__FILE__,__LINE__,image->numcomps,prec,
379 max_w,max_h, (void*)in_prof,(void*)out_prof);
381 fprintf(stderr,"\trender_intent (%u)\n\t"
382 "color_space: in(%#x)(%c%c%c%c) out:(%#x)(%c%c%c%c)\n\t"
383 " type: in(%u) out:(%u)\n",
386 (in_space>>24) & 0xff,(in_space>>16) & 0xff,
387 (in_space>>8) & 0xff, in_space & 0xff,
390 (out_space>>24) & 0xff,(out_space>>16) & 0xff,
391 (out_space>>8) & 0xff, out_space & 0xff,
398 #endif /* DEBUG_PROFILE */
400 transform = cmsCreateTransform(in_prof, in_type,
401 out_prof, out_type, intent, 0);
403 #ifdef OPJ_HAVE_LIBLCMS2
404 /* Possible for: LCMS_VERSION >= 2000 :*/
405 cmsCloseProfile(in_prof);
406 cmsCloseProfile(out_prof);
409 if(transform == NULL)
412 fprintf(stderr,"%s:%d:color_apply_icc_profile\n\tcmsCreateTransform failed. "
413 "ICC Profile ignored.\n",__FILE__,__LINE__);
415 image->color_space = oldspace;
416 #ifdef OPJ_HAVE_LIBLCMS1
417 cmsCloseProfile(in_prof);
418 cmsCloseProfile(out_prof);
423 if(image->numcomps > 2)/* RGB, RGBA */
427 unsigned char *inbuf, *outbuf, *in, *out;
429 nr_samples = (cmsUInt32Number)max * 3 * (cmsUInt32Number)sizeof(unsigned char);
430 in = inbuf = (unsigned char*)malloc(nr_samples);
431 out = outbuf = (unsigned char*)malloc(nr_samples);
433 r = image->comps[0].data;
434 g = image->comps[1].data;
435 b = image->comps[2].data;
437 for(i = 0; i < max; ++i)
439 *in++ = (unsigned char)*r++;
440 *in++ = (unsigned char)*g++;
441 *in++ = (unsigned char)*b++;
444 cmsDoTransform(transform, inbuf, outbuf, (cmsUInt32Number)max);
446 r = image->comps[0].data;
447 g = image->comps[1].data;
448 b = image->comps[2].data;
450 for(i = 0; i < max; ++i)
456 free(inbuf); free(outbuf);
460 unsigned short *inbuf, *outbuf, *in, *out;
462 nr_samples = (cmsUInt32Number)max * 3 * (cmsUInt32Number)sizeof(unsigned short);
463 in = inbuf = (unsigned short*)malloc(nr_samples);
464 out = outbuf = (unsigned short*)malloc(nr_samples);
466 r = image->comps[0].data;
467 g = image->comps[1].data;
468 b = image->comps[2].data;
470 for(i = 0; i < max; ++i)
472 *in++ = (unsigned short)*r++;
473 *in++ = (unsigned short)*g++;
474 *in++ = (unsigned short)*b++;
477 cmsDoTransform(transform, inbuf, outbuf, (cmsUInt32Number)max);
479 r = image->comps[0].data;
480 g = image->comps[1].data;
481 b = image->comps[2].data;
483 for(i = 0; i < max; ++i)
489 free(inbuf); free(outbuf);
492 else /* GRAY, GRAYA */
494 unsigned char *in, *inbuf, *out, *outbuf;
496 nr_samples = (cmsUInt32Number)max * 3 * sizeof(unsigned char);
497 in = inbuf = (unsigned char*)malloc(nr_samples);
498 out = outbuf = (unsigned char*)malloc(nr_samples);
500 image->comps = (opj_image_comp_t*)
501 realloc(image->comps, (image->numcomps+2)*sizeof(opj_image_comp_t));
503 if(image->numcomps == 2)
504 image->comps[3] = image->comps[1];
506 image->comps[1] = image->comps[0];
507 image->comps[2] = image->comps[0];
509 image->comps[1].data = (int*)calloc((size_t)max, sizeof(int));
510 image->comps[2].data = (int*)calloc((size_t)max, sizeof(int));
512 image->numcomps += 2;
514 r = image->comps[0].data;
516 for(i = 0; i < max; ++i)
518 *in++ = (unsigned char)*r++;
520 cmsDoTransform(transform, inbuf, outbuf, (cmsUInt32Number)max);
522 r = image->comps[0].data;
523 g = image->comps[1].data;
524 b = image->comps[2].data;
526 for(i = 0; i < max; ++i)
528 *r++ = (int)*out++; *g++ = (int)*out++; *b++ = (int)*out++;
530 free(inbuf); free(outbuf);
532 }/* if(image->numcomps */
534 cmsDeleteTransform(transform);
536 #ifdef OPJ_HAVE_LIBLCMS1
537 cmsCloseProfile(in_prof);
538 cmsCloseProfile(out_prof);
540 }/* color_apply_icc_profile() */
542 #endif /* OPJ_HAVE_LIBLCMS2 || OPJ_HAVE_LIBLCMS1 */