[trunk] Start FolderReorgProposal task
[openjpeg.git] / src / bin / common / color.c
1 /*
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
8  * All rights reserved.
9  *
10  * Redistribution and use in source and binary forms, with or without
11  * modification, are permitted provided that the following conditions
12  * are met:
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.
18  *
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.
30  */
31
32 #include <stdio.h>
33 #include <string.h>
34 #include <stdlib.h>
35 #include <math.h>
36
37 #include "opj_config.h"
38 #include "openjpeg.h"
39 #include "color.h"
40
41 #ifdef HAVE_LIBLCMS2
42 #include <lcms2.h>
43 #endif
44 #ifdef HAVE_LIBLCMS1
45 #include <lcms.h>
46 #endif
47
48 /*--------------------------------------------------------
49 Matrix for sYCC, Amendment 1 to IEC 61966-2-1
50
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
54
55 Inverse:
56
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)
60
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)
64 {
65         int r, g, b;
66
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;
70
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;
73
74         b = y + (int)(1.772 * (float)cb);
75         if(b < 0) b = 0; else if(b > upb) b = upb; *out_b = b;
76 }
77
78 static void sycc444_to_rgb(opj_image_t *img)
79 {
80         int *d0, *d1, *d2, *r, *g, *b;
81         const int *y, *cb, *cr;
82         int maxw, maxh, max, i, offset, upb;
83
84         i = img->comps[0].prec;
85         offset = 1<<(i - 1); upb = (1<<i)-1;
86
87         maxw = img->comps[0].w; maxh = img->comps[0].h;
88         max = maxw * maxh;
89
90         y = img->comps[0].data;
91         cb = img->comps[1].data;
92         cr = img->comps[2].data;
93
94         d0 = r = (int*)malloc(sizeof(int) * max);
95         d1 = g = (int*)malloc(sizeof(int) * max);
96         d2 = b = (int*)malloc(sizeof(int) * max);
97
98         for(i = 0; i < max; ++i)
99    {
100         sycc_to_rgb(offset, upb, *y, *cb, *cr, r, g, b);        
101
102         ++y; ++cb; ++cr; ++r; ++g; ++b;
103    }    
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;
107
108 }/* sycc444_to_rgb() */
109
110 static void sycc422_to_rgb(opj_image_t *img)
111 {       
112         int *d0, *d1, *d2, *r, *g, *b;
113         const int *y, *cb, *cr;
114         int maxw, maxh, max, offset, upb;
115         int i, j;
116
117         i = img->comps[0].prec;
118         offset = 1<<(i - 1); upb = (1<<i)-1;
119
120         maxw = img->comps[0].w; maxh = img->comps[0].h;
121         max = maxw * maxh;
122
123         y = img->comps[0].data;
124         cb = img->comps[1].data;
125         cr = img->comps[2].data;
126
127         d0 = r = (int*)malloc(sizeof(int) * max);
128         d1 = g = (int*)malloc(sizeof(int) * max);
129         d2 = b = (int*)malloc(sizeof(int) * max);
130
131         for(i=0; i < maxh; ++i)
132    {
133         for(j=0; j < maxw; j += 2)
134   {
135         sycc_to_rgb(offset, upb, *y, *cb, *cr, r, g, b);
136
137         ++y; ++r; ++g; ++b;
138
139         sycc_to_rgb(offset, upb, *y, *cb, *cr, r, g, b);
140
141         ++y; ++r; ++g; ++b; ++cb; ++cr;
142   }
143    }
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;
147
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;
154
155 }/* sycc422_to_rgb() */
156
157 static void sycc420_to_rgb(opj_image_t *img)
158 {
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;
162         int i, j;
163
164         i = img->comps[0].prec;
165         offset = 1<<(i - 1); upb = (1<<i)-1;
166
167         maxw = img->comps[0].w; maxh = img->comps[0].h;
168         max = maxw * maxh;
169
170         y = img->comps[0].data;
171         cb = img->comps[1].data;
172         cr = img->comps[2].data;
173
174         d0 = r = (int*)malloc(sizeof(int) * max);
175         d1 = g = (int*)malloc(sizeof(int) * max);
176         d2 = b = (int*)malloc(sizeof(int) * max);
177
178         for(i=0; i < maxh; i += 2)
179    {
180         ny = y + maxw;
181         nr = r + maxw; ng = g + maxw; nb = b + maxw;
182
183         for(j=0; j < maxw;  j += 2)
184   {
185         sycc_to_rgb(offset, upb, *y, *cb, *cr, r, g, b);
186
187         ++y; ++r; ++g; ++b;
188
189         sycc_to_rgb(offset, upb, *y, *cb, *cr, r, g, b);
190
191         ++y; ++r; ++g; ++b;
192
193         sycc_to_rgb(offset, upb, *ny, *cb, *cr, nr, ng, nb);
194
195         ++ny; ++nr; ++ng; ++nb;
196
197         sycc_to_rgb(offset, upb, *ny, *cb, *cr, nr, ng, nb);
198
199         ++ny; ++nr; ++ng; ++nb; ++cb; ++cr;
200   }
201         y += maxw; r += maxw; g += maxw; b += maxw;
202    }
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;
206
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;
213
214 }/* sycc420_to_rgb() */
215
216 void color_sycc_to_rgb(opj_image_t *img)
217 {
218         if(img->numcomps < 3) 
219    {
220         img->color_space = CLRSPC_GRAY;
221         return;
222    }
223
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 */
230   {
231         sycc420_to_rgb(img);
232   }
233         else
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 */
240   {
241         sycc422_to_rgb(img);
242   }
243         else
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 */
250   {
251         sycc444_to_rgb(img);
252   }
253         else
254   {
255         fprintf(stderr,"%s:%d:color_sycc_to_rgb\n\tCAN NOT CONVERT\n",
256          __FILE__,__LINE__);
257         return;
258   }
259         img->color_space = CLRSPC_SRGB;
260
261 }/* color_sycc_to_rgb() */
262
263 #if defined(HAVE_LIBLCMS2) || defined(HAVE_LIBLCMS1)
264 #ifdef 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
274
275 #define cmsColorSpaceSignature icColorSpaceSignature
276 #define cmsGetHeaderRenderingIntent cmsTakeRenderingIntent
277
278 #endif /* HAVE_LIBLCMS1 */
279
280 void color_apply_icc_profile(opj_image_t *image)
281 {
282         cmsHPROFILE in_prof, out_prof;
283         cmsHTRANSFORM transform;
284         cmsColorSpaceSignature in_space, out_space;
285         cmsUInt32Number intent, in_type, out_type, nr_samples;
286         int *r, *g, *b;
287         int prec, i, max, max_w, max_h;
288         OPJ_COLOR_SPACE oldspace;
289
290         in_prof = 
291          cmsOpenProfileFromMem(image->icc_profile_buf, image->icc_profile_len);
292
293         if(in_prof == NULL) return;
294
295         in_space = cmsGetPCS(in_prof);
296         out_space = cmsGetColorSpace(in_prof);
297         intent = cmsGetHeaderRenderingIntent(in_prof);
298
299         
300         max_w = image->comps[0].w; max_h = image->comps[0].h;
301         prec = image->comps[0].prec;
302         oldspace = image->color_space;
303
304         if(out_space == cmsSigRgbData) /* enumCS 16 */
305    {
306         in_type = TYPE_RGB_16;
307         out_type = TYPE_RGB_16;
308         out_prof = cmsCreate_sRGBProfile();
309         image->color_space = CLRSPC_SRGB;
310    }
311         else
312         if(out_space == cmsSigGrayData) /* enumCS 17 */
313    {
314         in_type = TYPE_GRAY_8;
315         out_type = TYPE_RGB_8;
316         out_prof = cmsCreate_sRGBProfile();
317         image->color_space = CLRSPC_SRGB;
318    }
319         else
320         if(out_space == cmsSigYCbCrData) /* enumCS 18 */
321    {
322         in_type = TYPE_YCbCr_16;
323         out_type = TYPE_RGB_16;
324         out_prof = cmsCreate_sRGBProfile();
325         image->color_space = CLRSPC_SRGB;
326    }
327         else
328    {
329 #ifdef DEBUG_PROFILE
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);
335 #endif
336         return;
337    }
338
339 #ifdef DEBUG_PROFILE
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);
343
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",
347 intent,
348 in_space,
349 (in_space>>24) & 0xff,(in_space>>16) & 0xff,
350 (in_space>>8) & 0xff, in_space & 0xff,
351
352 out_space,
353 (out_space>>24) & 0xff,(out_space>>16) & 0xff,
354 (out_space>>8) & 0xff, out_space & 0xff,
355
356 in_type,out_type
357  );
358 #endif /* DEBUG_PROFILE */
359
360         transform = cmsCreateTransform(in_prof, in_type,
361          out_prof, out_type, intent, 0);
362
363 #ifdef HAVE_LIBLCMS2
364 /* Possible for: LCMS_VERSION >= 2000 :*/
365         cmsCloseProfile(in_prof);
366         cmsCloseProfile(out_prof);
367 #endif
368
369         if(transform == NULL)
370    {
371 #ifdef DEBUG_PROFILE
372 fprintf(stderr,"%s:%d:color_apply_icc_profile\n\tcmsCreateTransform failed. "
373 "ICC Profile ignored.\n",__FILE__,__LINE__);
374 #endif
375         image->color_space = oldspace;
376 #ifdef HAVE_LIBLCMS1
377         cmsCloseProfile(in_prof);
378         cmsCloseProfile(out_prof);
379 #endif
380         return;
381    }
382
383         if(image->numcomps > 2)/* RGB, RGBA */
384    {
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);
389
390         r = image->comps[0].data;
391         g = image->comps[1].data;
392         b = image->comps[2].data;
393
394         for(i = 0; i < max; ++i)
395   {
396         *in++ = (unsigned short)*r++;
397         *in++ = (unsigned short)*g++;
398         *in++ = (unsigned short)*b++;
399   }
400
401         cmsDoTransform(transform, inbuf, outbuf, max);
402
403         r = image->comps[0].data;
404         g = image->comps[1].data;
405         b = image->comps[2].data;
406
407         for(i = 0; i < max; ++i)
408   {
409         *r++ = (int)*out++;
410         *g++ = (int)*out++;
411         *b++ = (int)*out++;
412   }
413         free(inbuf); free(outbuf);
414    }
415         else /* GRAY, GRAYA */
416    {
417         unsigned char *in, *inbuf, *out, *outbuf;
418
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);
422
423         image->comps = (opj_image_comp_t*)
424          realloc(image->comps, (image->numcomps+2)*sizeof(opj_image_comp_t));
425
426         if(image->numcomps == 2)
427          image->comps[3] = image->comps[1];
428
429         image->comps[1] = image->comps[0];
430         image->comps[2] = image->comps[0];
431
432         image->comps[1].data = (int*)calloc(max, sizeof(int));
433         image->comps[2].data = (int*)calloc(max, sizeof(int));
434
435         image->numcomps += 2;
436
437         r = image->comps[0].data;
438
439         for(i = 0; i < max; ++i)
440   {
441         *in++ = (unsigned char)*r++;
442   }
443         cmsDoTransform(transform, inbuf, outbuf, max);
444
445         r = image->comps[0].data;
446         g = image->comps[1].data;
447         b = image->comps[2].data;
448
449         for(i = 0; i < max; ++i)
450   {
451         *r++ = (int)*out++; *g++ = (int)*out++; *b++ = (int)*out++;
452   }
453         free(inbuf); free(outbuf);
454
455    }/* if(image->numcomps */
456
457         cmsDeleteTransform(transform);
458
459 #ifdef HAVE_LIBLCMS1
460         cmsCloseProfile(in_prof);
461         cmsCloseProfile(out_prof);
462 #endif
463 }/* color_apply_icc_profile() */
464
465 #endif /* HAVE_LIBLCMS2 || HAVE_LIBLCMS1 */
466