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.
37 #include "opj_config.h"
48 /*--------------------------------------------------------
49 Matrix for sYCC, Amendment 1 to IEC 61966-2-1
51 Y : 0.299 0.587 0.114 :R
52 Cb: -0.1687 -0.3312 0.5 :G
53 Cr: 0.5 -0.4187 -0.0812 :B
57 R: 1 -3.68213e-05 1.40199 :Y
58 G: 1.00003 -0.344125 -0.714128 :Cb - 2^(prec - 1)
59 B: 0.999823 1.77204 -8.04142e-06 :Cr - 2^(prec - 1)
61 -----------------------------------------------------------*/
62 static void sycc_to_rgb(int offset, int upb, int y, int cb, int cr,
63 int *out_r, int *out_g, int *out_b)
67 cb -= offset; cr -= offset;
68 r = y + (int)(1.402 * (float)cr);
69 if(r < 0) r = 0; else if(r > upb) r = upb; *out_r = r;
71 g = y - (int)(0.344 * (float)cb + 0.714 * (float)cr);
72 if(g < 0) g = 0; else if(g > upb) g = upb; *out_g = g;
74 b = y + (int)(1.772 * (float)cb);
75 if(b < 0) b = 0; else if(b > upb) b = upb; *out_b = b;
78 static void sycc444_to_rgb(opj_image_t *img)
80 int *d0, *d1, *d2, *r, *g, *b;
81 const int *y, *cb, *cr;
82 int maxw, maxh, max, i, offset, upb;
84 i = img->comps[0].prec;
85 offset = 1<<(i - 1); upb = (1<<i)-1;
87 maxw = img->comps[0].w; maxh = img->comps[0].h;
90 y = img->comps[0].data;
91 cb = img->comps[1].data;
92 cr = img->comps[2].data;
94 d0 = r = (int*)malloc(sizeof(int) * max);
95 d1 = g = (int*)malloc(sizeof(int) * max);
96 d2 = b = (int*)malloc(sizeof(int) * max);
98 for(i = 0; i < max; ++i)
100 sycc_to_rgb(offset, upb, *y, *cb, *cr, r, g, b);
102 ++y; ++cb; ++cr; ++r; ++g; ++b;
104 free(img->comps[0].data); img->comps[0].data = d0;
105 free(img->comps[1].data); img->comps[1].data = d1;
106 free(img->comps[2].data); img->comps[2].data = d2;
108 }/* sycc444_to_rgb() */
110 static void sycc422_to_rgb(opj_image_t *img)
112 int *d0, *d1, *d2, *r, *g, *b;
113 const int *y, *cb, *cr;
114 int maxw, maxh, max, offset, upb;
117 i = img->comps[0].prec;
118 offset = 1<<(i - 1); upb = (1<<i)-1;
120 maxw = img->comps[0].w; maxh = img->comps[0].h;
123 y = img->comps[0].data;
124 cb = img->comps[1].data;
125 cr = img->comps[2].data;
127 d0 = r = (int*)malloc(sizeof(int) * max);
128 d1 = g = (int*)malloc(sizeof(int) * max);
129 d2 = b = (int*)malloc(sizeof(int) * max);
131 for(i=0; i < maxh; ++i)
133 for(j=0; j < maxw; j += 2)
135 sycc_to_rgb(offset, upb, *y, *cb, *cr, r, g, b);
139 sycc_to_rgb(offset, upb, *y, *cb, *cr, r, g, b);
141 ++y; ++r; ++g; ++b; ++cb; ++cr;
144 free(img->comps[0].data); img->comps[0].data = d0;
145 free(img->comps[1].data); img->comps[1].data = d1;
146 free(img->comps[2].data); img->comps[2].data = d2;
148 img->comps[1].w = maxw; img->comps[1].h = maxh;
149 img->comps[2].w = maxw; img->comps[2].h = maxh;
150 img->comps[1].dx = img->comps[0].dx;
151 img->comps[2].dx = img->comps[0].dx;
152 img->comps[1].dy = img->comps[0].dy;
153 img->comps[2].dy = img->comps[0].dy;
155 }/* sycc422_to_rgb() */
157 static void sycc420_to_rgb(opj_image_t *img)
159 int *d0, *d1, *d2, *r, *g, *b, *nr, *ng, *nb;
160 const int *y, *cb, *cr, *ny;
161 int maxw, maxh, max, offset, upb;
164 i = img->comps[0].prec;
165 offset = 1<<(i - 1); upb = (1<<i)-1;
167 maxw = img->comps[0].w; maxh = img->comps[0].h;
170 y = img->comps[0].data;
171 cb = img->comps[1].data;
172 cr = img->comps[2].data;
174 d0 = r = (int*)malloc(sizeof(int) * max);
175 d1 = g = (int*)malloc(sizeof(int) * max);
176 d2 = b = (int*)malloc(sizeof(int) * max);
178 for(i=0; i < maxh; i += 2)
181 nr = r + maxw; ng = g + maxw; nb = b + maxw;
183 for(j=0; j < maxw; j += 2)
185 sycc_to_rgb(offset, upb, *y, *cb, *cr, r, g, b);
189 sycc_to_rgb(offset, upb, *y, *cb, *cr, r, g, b);
193 sycc_to_rgb(offset, upb, *ny, *cb, *cr, nr, ng, nb);
195 ++ny; ++nr; ++ng; ++nb;
197 sycc_to_rgb(offset, upb, *ny, *cb, *cr, nr, ng, nb);
199 ++ny; ++nr; ++ng; ++nb; ++cb; ++cr;
201 y += maxw; r += maxw; g += maxw; b += maxw;
203 free(img->comps[0].data); img->comps[0].data = d0;
204 free(img->comps[1].data); img->comps[1].data = d1;
205 free(img->comps[2].data); img->comps[2].data = d2;
207 img->comps[1].w = maxw; img->comps[1].h = maxh;
208 img->comps[2].w = maxw; img->comps[2].h = maxh;
209 img->comps[1].dx = img->comps[0].dx;
210 img->comps[2].dx = img->comps[0].dx;
211 img->comps[1].dy = img->comps[0].dy;
212 img->comps[2].dy = img->comps[0].dy;
214 }/* sycc420_to_rgb() */
216 void color_sycc_to_rgb(opj_image_t *img)
218 if(img->numcomps < 3)
220 img->color_space = CLRSPC_GRAY;
224 if((img->comps[0].dx == 1)
225 && (img->comps[1].dx == 2)
226 && (img->comps[2].dx == 2)
227 && (img->comps[0].dy == 1)
228 && (img->comps[1].dy == 2)
229 && (img->comps[2].dy == 2))/* horizontal and vertical sub-sample */
234 if((img->comps[0].dx == 1)
235 && (img->comps[1].dx == 2)
236 && (img->comps[2].dx == 2)
237 && (img->comps[0].dy == 1)
238 && (img->comps[1].dy == 1)
239 && (img->comps[2].dy == 1))/* horizontal sub-sample only */
244 if((img->comps[0].dx == 1)
245 && (img->comps[1].dx == 1)
246 && (img->comps[2].dx == 1)
247 && (img->comps[0].dy == 1)
248 && (img->comps[1].dy == 1)
249 && (img->comps[2].dy == 1))/* no sub-sample */
255 fprintf(stderr,"%s:%d:color_sycc_to_rgb\n\tCAN NOT CONVERT\n",
259 img->color_space = CLRSPC_SRGB;
261 }/* color_sycc_to_rgb() */
263 #if defined(HAVE_LIBLCMS2) || defined(HAVE_LIBLCMS1)
265 /* Bob Friesenhahn proposed:*/
266 #define cmsSigXYZData icSigXYZData
267 #define cmsSigLabData icSigLabData
268 #define cmsSigCmykData icSigCmykData
269 #define cmsSigYCbCrData icSigYCbCrData
270 #define cmsSigLuvData icSigLuvData
271 #define cmsSigGrayData icSigGrayData
272 #define cmsSigRgbData icSigRgbData
273 #define cmsUInt32Number DWORD
275 #define cmsColorSpaceSignature icColorSpaceSignature
276 #define cmsGetHeaderRenderingIntent cmsTakeRenderingIntent
278 #endif /* HAVE_LIBLCMS1 */
280 void color_apply_icc_profile(opj_image_t *image)
282 cmsHPROFILE in_prof, out_prof;
283 cmsHTRANSFORM transform;
284 cmsColorSpaceSignature in_space, out_space;
285 cmsUInt32Number intent, in_type, out_type, nr_samples;
287 int prec, i, max, max_w, max_h;
288 OPJ_COLOR_SPACE oldspace;
291 cmsOpenProfileFromMem(image->icc_profile_buf, image->icc_profile_len);
293 if(in_prof == NULL) return;
295 in_space = cmsGetPCS(in_prof);
296 out_space = cmsGetColorSpace(in_prof);
297 intent = cmsGetHeaderRenderingIntent(in_prof);
300 max_w = image->comps[0].w; max_h = image->comps[0].h;
301 prec = image->comps[0].prec;
302 oldspace = image->color_space;
304 if(out_space == cmsSigRgbData) /* enumCS 16 */
306 in_type = TYPE_RGB_16;
307 out_type = TYPE_RGB_16;
308 out_prof = cmsCreate_sRGBProfile();
309 image->color_space = CLRSPC_SRGB;
312 if(out_space == cmsSigGrayData) /* enumCS 17 */
314 in_type = TYPE_GRAY_8;
315 out_type = TYPE_RGB_8;
316 out_prof = cmsCreate_sRGBProfile();
317 image->color_space = CLRSPC_SRGB;
320 if(out_space == cmsSigYCbCrData) /* enumCS 18 */
322 in_type = TYPE_YCbCr_16;
323 out_type = TYPE_RGB_16;
324 out_prof = cmsCreate_sRGBProfile();
325 image->color_space = CLRSPC_SRGB;
330 fprintf(stderr,"%s:%d: color_apply_icc_profile\n\tICC Profile has unknown "
331 "output colorspace(%#x)(%c%c%c%c)\n\tICC Profile ignored.\n",
332 __FILE__,__LINE__,out_space,
333 (out_space>>24) & 0xff,(out_space>>16) & 0xff,
334 (out_space>>8) & 0xff, out_space & 0xff);
340 fprintf(stderr,"%s:%d:color_apply_icc_profile\n\tchannels(%d) prec(%d) w(%d) h(%d)"
341 "\n\tprofile: in(%p) out(%p)\n",__FILE__,__LINE__,image->numcomps,prec,
342 max_w,max_h, (void*)in_prof,(void*)out_prof);
344 fprintf(stderr,"\trender_intent (%u)\n\t"
345 "color_space: in(%#x)(%c%c%c%c) out:(%#x)(%c%c%c%c)\n\t"
346 " type: in(%u) out:(%u)\n",
349 (in_space>>24) & 0xff,(in_space>>16) & 0xff,
350 (in_space>>8) & 0xff, in_space & 0xff,
353 (out_space>>24) & 0xff,(out_space>>16) & 0xff,
354 (out_space>>8) & 0xff, out_space & 0xff,
358 #endif /* DEBUG_PROFILE */
360 transform = cmsCreateTransform(in_prof, in_type,
361 out_prof, out_type, intent, 0);
364 /* Possible for: LCMS_VERSION >= 2000 :*/
365 cmsCloseProfile(in_prof);
366 cmsCloseProfile(out_prof);
369 if(transform == NULL)
372 fprintf(stderr,"%s:%d:color_apply_icc_profile\n\tcmsCreateTransform failed. "
373 "ICC Profile ignored.\n",__FILE__,__LINE__);
375 image->color_space = oldspace;
377 cmsCloseProfile(in_prof);
378 cmsCloseProfile(out_prof);
383 if(image->numcomps > 2)/* RGB, RGBA */
385 unsigned short *inbuf, *outbuf, *in, *out;
386 max = max_w * max_h; nr_samples = max * 3 * sizeof(unsigned short);
387 in = inbuf = (unsigned short*)malloc(nr_samples);
388 out = outbuf = (unsigned short*)malloc(nr_samples);
390 r = image->comps[0].data;
391 g = image->comps[1].data;
392 b = image->comps[2].data;
394 for(i = 0; i < max; ++i)
396 *in++ = (unsigned short)*r++;
397 *in++ = (unsigned short)*g++;
398 *in++ = (unsigned short)*b++;
401 cmsDoTransform(transform, inbuf, outbuf, max);
403 r = image->comps[0].data;
404 g = image->comps[1].data;
405 b = image->comps[2].data;
407 for(i = 0; i < max; ++i)
413 free(inbuf); free(outbuf);
415 else /* GRAY, GRAYA */
417 unsigned char *in, *inbuf, *out, *outbuf;
419 max = max_w * max_h; nr_samples = max * 3 * sizeof(unsigned char);
420 in = inbuf = (unsigned char*)malloc(nr_samples);
421 out = outbuf = (unsigned char*)malloc(nr_samples);
423 image->comps = (opj_image_comp_t*)
424 realloc(image->comps, (image->numcomps+2)*sizeof(opj_image_comp_t));
426 if(image->numcomps == 2)
427 image->comps[3] = image->comps[1];
429 image->comps[1] = image->comps[0];
430 image->comps[2] = image->comps[0];
432 image->comps[1].data = (int*)calloc(max, sizeof(int));
433 image->comps[2].data = (int*)calloc(max, sizeof(int));
435 image->numcomps += 2;
437 r = image->comps[0].data;
439 for(i = 0; i < max; ++i)
441 *in++ = (unsigned char)*r++;
443 cmsDoTransform(transform, inbuf, outbuf, max);
445 r = image->comps[0].data;
446 g = image->comps[1].data;
447 b = image->comps[2].data;
449 for(i = 0; i < max; ++i)
451 *r++ = (int)*out++; *g++ = (int)*out++; *b++ = (int)*out++;
453 free(inbuf); free(outbuf);
455 }/* if(image->numcomps */
457 cmsDeleteTransform(transform);
460 cmsCloseProfile(in_prof);
461 cmsCloseProfile(out_prof);
463 }/* color_apply_icc_profile() */
465 #endif /* HAVE_LIBLCMS2 || HAVE_LIBLCMS1 */