[trunk] Remove 2 warnings about set but not used variables
[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_apps_config.h"
38 #include "openjpeg.h"
39 #include "color.h"
40
41 #ifdef OPJ_HAVE_LIBLCMS2
42 #include <lcms2.h>
43 #endif
44 #ifdef OPJ_HAVE_LIBLCMS1
45 #include <lcms.h>
46 #endif
47
48 #ifdef OPJ_USE_LEGACY
49 #define OPJ_CLRSPC_GRAY CLRSPC_GRAY
50 #define OPJ_CLRSPC_SRGB CLRSPC_SRGB
51 #endif
52
53 /*--------------------------------------------------------
54 Matrix for sYCC, Amendment 1 to IEC 61966-2-1
55
56 Y :   0.299   0.587    0.114   :R
57 Cb:  -0.1687 -0.3312   0.5     :G
58 Cr:   0.5    -0.4187  -0.0812  :B
59
60 Inverse:
61
62 R: 1        -3.68213e-05    1.40199      :Y
63 G: 1.00003  -0.344125      -0.714128     :Cb - 2^(prec - 1)
64 B: 0.999823  1.77204       -8.04142e-06  :Cr - 2^(prec - 1)
65
66 -----------------------------------------------------------*/
67 static void sycc_to_rgb(int offset, int upb, int y, int cb, int cr,
68         int *out_r, int *out_g, int *out_b)
69 {
70         int r, g, b;
71
72         cb -= offset; cr -= offset;
73         r = y + (int)(1.402 * (float)cr);
74         if(r < 0) r = 0; else if(r > upb) r = upb; *out_r = r;
75
76         g = y - (int)(0.344 * (float)cb + 0.714 * (float)cr);
77         if(g < 0) g = 0; else if(g > upb) g = upb; *out_g = g;
78
79         b = y + (int)(1.772 * (float)cb);
80         if(b < 0) b = 0; else if(b > upb) b = upb; *out_b = b;
81 }
82
83 static void sycc444_to_rgb(opj_image_t *img)
84 {
85         int *d0, *d1, *d2, *r, *g, *b;
86         const int *y, *cb, *cr;
87         int maxw, maxh, max, i, offset, upb;
88
89         i = img->comps[0].prec;
90         offset = 1<<(i - 1); upb = (1<<i)-1;
91
92         maxw = img->comps[0].w; maxh = img->comps[0].h;
93         max = maxw * maxh;
94
95         y = img->comps[0].data;
96         cb = img->comps[1].data;
97         cr = img->comps[2].data;
98
99         d0 = r = (int*)malloc(sizeof(int) * max);
100         d1 = g = (int*)malloc(sizeof(int) * max);
101         d2 = b = (int*)malloc(sizeof(int) * max);
102
103         for(i = 0; i < max; ++i)
104    {
105         sycc_to_rgb(offset, upb, *y, *cb, *cr, r, g, b);        
106
107         ++y; ++cb; ++cr; ++r; ++g; ++b;
108    }    
109         free(img->comps[0].data); img->comps[0].data = d0;
110         free(img->comps[1].data); img->comps[1].data = d1;
111         free(img->comps[2].data); img->comps[2].data = d2;
112
113 }/* sycc444_to_rgb() */
114
115 static void sycc422_to_rgb(opj_image_t *img)
116 {       
117         int *d0, *d1, *d2, *r, *g, *b;
118         const int *y, *cb, *cr;
119         int maxw, maxh, max, offset, upb;
120         int i, j;
121
122         i = img->comps[0].prec;
123         offset = 1<<(i - 1); upb = (1<<i)-1;
124
125         maxw = img->comps[0].w; maxh = img->comps[0].h;
126         max = maxw * maxh;
127
128         y = img->comps[0].data;
129         cb = img->comps[1].data;
130         cr = img->comps[2].data;
131
132         d0 = r = (int*)malloc(sizeof(int) * max);
133         d1 = g = (int*)malloc(sizeof(int) * max);
134         d2 = b = (int*)malloc(sizeof(int) * max);
135
136         for(i=0; i < maxh; ++i)
137    {
138         for(j=0; j < maxw; j += 2)
139   {
140         sycc_to_rgb(offset, upb, *y, *cb, *cr, r, g, b);
141
142         ++y; ++r; ++g; ++b;
143
144         sycc_to_rgb(offset, upb, *y, *cb, *cr, r, g, b);
145
146         ++y; ++r; ++g; ++b; ++cb; ++cr;
147   }
148    }
149         free(img->comps[0].data); img->comps[0].data = d0;
150         free(img->comps[1].data); img->comps[1].data = d1;
151         free(img->comps[2].data); img->comps[2].data = d2;
152
153         img->comps[1].w = maxw; img->comps[1].h = maxh;
154         img->comps[2].w = maxw; img->comps[2].h = maxh;
155         img->comps[1].dx = img->comps[0].dx;
156         img->comps[2].dx = img->comps[0].dx;
157         img->comps[1].dy = img->comps[0].dy;
158         img->comps[2].dy = img->comps[0].dy;
159
160 }/* sycc422_to_rgb() */
161
162 static void sycc420_to_rgb(opj_image_t *img)
163 {
164         int *d0, *d1, *d2, *r, *g, *b, *nr, *ng, *nb;
165         const int *y, *cb, *cr, *ny;
166         int maxw, maxh, max, offset, upb;
167         int i, j;
168
169         i = img->comps[0].prec;
170         offset = 1<<(i - 1); upb = (1<<i)-1;
171
172         maxw = img->comps[0].w; maxh = img->comps[0].h;
173         max = maxw * maxh;
174
175         y = img->comps[0].data;
176         cb = img->comps[1].data;
177         cr = img->comps[2].data;
178
179         d0 = r = (int*)malloc(sizeof(int) * max);
180         d1 = g = (int*)malloc(sizeof(int) * max);
181         d2 = b = (int*)malloc(sizeof(int) * max);
182
183         for(i=0; i < maxh; i += 2)
184    {
185         ny = y + maxw;
186         nr = r + maxw; ng = g + maxw; nb = b + maxw;
187
188         for(j=0; j < maxw;  j += 2)
189   {
190         sycc_to_rgb(offset, upb, *y, *cb, *cr, r, g, b);
191
192         ++y; ++r; ++g; ++b;
193
194         sycc_to_rgb(offset, upb, *y, *cb, *cr, r, g, b);
195
196         ++y; ++r; ++g; ++b;
197
198         sycc_to_rgb(offset, upb, *ny, *cb, *cr, nr, ng, nb);
199
200         ++ny; ++nr; ++ng; ++nb;
201
202         sycc_to_rgb(offset, upb, *ny, *cb, *cr, nr, ng, nb);
203
204         ++ny; ++nr; ++ng; ++nb; ++cb; ++cr;
205   }
206         y += maxw; r += maxw; g += maxw; b += maxw;
207    }
208         free(img->comps[0].data); img->comps[0].data = d0;
209         free(img->comps[1].data); img->comps[1].data = d1;
210         free(img->comps[2].data); img->comps[2].data = d2;
211
212         img->comps[1].w = maxw; img->comps[1].h = maxh;
213         img->comps[2].w = maxw; img->comps[2].h = maxh;
214         img->comps[1].dx = img->comps[0].dx;
215         img->comps[2].dx = img->comps[0].dx;
216         img->comps[1].dy = img->comps[0].dy;
217         img->comps[2].dy = img->comps[0].dy;
218
219 }/* sycc420_to_rgb() */
220
221 void color_sycc_to_rgb(opj_image_t *img)
222 {
223         if(img->numcomps < 3) 
224    {
225         img->color_space = OPJ_CLRSPC_GRAY;
226         return;
227    }
228
229         if((img->comps[0].dx == 1)
230         && (img->comps[1].dx == 2)
231         && (img->comps[2].dx == 2)
232         && (img->comps[0].dy == 1)
233         && (img->comps[1].dy == 2)
234         && (img->comps[2].dy == 2))/* horizontal and vertical sub-sample */
235   {
236         sycc420_to_rgb(img);
237   }
238         else
239         if((img->comps[0].dx == 1)
240         && (img->comps[1].dx == 2)
241         && (img->comps[2].dx == 2)
242         && (img->comps[0].dy == 1)
243         && (img->comps[1].dy == 1)
244         && (img->comps[2].dy == 1))/* horizontal sub-sample only */
245   {
246         sycc422_to_rgb(img);
247   }
248         else
249         if((img->comps[0].dx == 1)
250         && (img->comps[1].dx == 1)
251         && (img->comps[2].dx == 1)
252         && (img->comps[0].dy == 1)
253         && (img->comps[1].dy == 1)
254         && (img->comps[2].dy == 1))/* no sub-sample */
255   {
256         sycc444_to_rgb(img);
257   }
258         else
259   {
260         fprintf(stderr,"%s:%d:color_sycc_to_rgb\n\tCAN NOT CONVERT\n",
261          __FILE__,__LINE__);
262         return;
263   }
264         img->color_space = OPJ_CLRSPC_SRGB;
265
266 }/* color_sycc_to_rgb() */
267
268 #if defined(OPJ_HAVE_LIBLCMS2) || defined(OPJ_HAVE_LIBLCMS1)
269 #ifdef OPJ_HAVE_LIBLCMS1
270 /* Bob Friesenhahn proposed:*/
271 #define cmsSigXYZData   icSigXYZData
272 #define cmsSigLabData   icSigLabData
273 #define cmsSigCmykData  icSigCmykData
274 #define cmsSigYCbCrData icSigYCbCrData
275 #define cmsSigLuvData   icSigLuvData
276 #define cmsSigGrayData  icSigGrayData
277 #define cmsSigRgbData   icSigRgbData
278 #define cmsUInt32Number DWORD
279
280 #define cmsColorSpaceSignature icColorSpaceSignature
281 #define cmsGetHeaderRenderingIntent cmsTakeRenderingIntent
282
283 #endif /* OPJ_HAVE_LIBLCMS1 */
284
285 void color_apply_icc_profile(opj_image_t *image)
286 {
287         cmsHPROFILE in_prof, out_prof;
288         cmsHTRANSFORM transform;
289         cmsColorSpaceSignature in_space, out_space;
290         cmsUInt32Number intent, in_type, out_type, nr_samples;
291         int *r, *g, *b;
292         int prec, i, max, max_w, max_h;
293         OPJ_COLOR_SPACE oldspace;
294
295         in_prof = 
296          cmsOpenProfileFromMem(image->icc_profile_buf, image->icc_profile_len);
297
298         if(in_prof == NULL) return;
299
300         in_space = cmsGetPCS(in_prof);
301         out_space = cmsGetColorSpace(in_prof);
302         intent = cmsGetHeaderRenderingIntent(in_prof);
303
304         
305         max_w = image->comps[0].w; max_h = image->comps[0].h;
306         prec = image->comps[0].prec;
307         oldspace = image->color_space;
308
309         if(out_space == cmsSigRgbData) /* enumCS 16 */
310    {
311         in_type = TYPE_RGB_16;
312         out_type = TYPE_RGB_16;
313         out_prof = cmsCreate_sRGBProfile();
314         image->color_space = OPJ_CLRSPC_SRGB;
315    }
316         else
317         if(out_space == cmsSigGrayData) /* enumCS 17 */
318    {
319         in_type = TYPE_GRAY_8;
320         out_type = TYPE_RGB_8;
321         out_prof = cmsCreate_sRGBProfile();
322         image->color_space = OPJ_CLRSPC_SRGB;
323    }
324         else
325         if(out_space == cmsSigYCbCrData) /* enumCS 18 */
326    {
327         in_type = TYPE_YCbCr_16;
328         out_type = TYPE_RGB_16;
329         out_prof = cmsCreate_sRGBProfile();
330         image->color_space = OPJ_CLRSPC_SRGB;
331    }
332         else
333    {
334 #ifdef DEBUG_PROFILE
335 fprintf(stderr,"%s:%d: color_apply_icc_profile\n\tICC Profile has unknown "
336 "output colorspace(%#x)(%c%c%c%c)\n\tICC Profile ignored.\n",
337 __FILE__,__LINE__,out_space,
338 (out_space>>24) & 0xff,(out_space>>16) & 0xff,
339 (out_space>>8) & 0xff, out_space & 0xff);
340 #endif
341         return;
342    }
343
344 #ifdef DEBUG_PROFILE
345 fprintf(stderr,"%s:%d:color_apply_icc_profile\n\tchannels(%d) prec(%d) w(%d) h(%d)"
346 "\n\tprofile: in(%p) out(%p)\n",__FILE__,__LINE__,image->numcomps,prec,
347 max_w,max_h, (void*)in_prof,(void*)out_prof);
348
349 fprintf(stderr,"\trender_intent (%u)\n\t"
350 "color_space: in(%#x)(%c%c%c%c)   out:(%#x)(%c%c%c%c)\n\t"
351 "       type: in(%u)              out:(%u)\n",
352 intent,
353 in_space,
354 (in_space>>24) & 0xff,(in_space>>16) & 0xff,
355 (in_space>>8) & 0xff, in_space & 0xff,
356
357 out_space,
358 (out_space>>24) & 0xff,(out_space>>16) & 0xff,
359 (out_space>>8) & 0xff, out_space & 0xff,
360
361 in_type,out_type
362  );
363 #else
364   (void)prec;
365   (void)in_space;
366 #endif /* DEBUG_PROFILE */
367
368         transform = cmsCreateTransform(in_prof, in_type,
369          out_prof, out_type, intent, 0);
370
371 #ifdef OPJ_HAVE_LIBLCMS2
372 /* Possible for: LCMS_VERSION >= 2000 :*/
373         cmsCloseProfile(in_prof);
374         cmsCloseProfile(out_prof);
375 #endif
376
377         if(transform == NULL)
378    {
379 #ifdef DEBUG_PROFILE
380 fprintf(stderr,"%s:%d:color_apply_icc_profile\n\tcmsCreateTransform failed. "
381 "ICC Profile ignored.\n",__FILE__,__LINE__);
382 #endif
383         image->color_space = oldspace;
384 #ifdef OPJ_HAVE_LIBLCMS1
385         cmsCloseProfile(in_prof);
386         cmsCloseProfile(out_prof);
387 #endif
388         return;
389    }
390
391         if(image->numcomps > 2)/* RGB, RGBA */
392    {
393         unsigned short *inbuf, *outbuf, *in, *out;
394         max = max_w * max_h;
395   nr_samples = (cmsUInt32Number)(max * 3 * sizeof(unsigned short));
396         in = inbuf = (unsigned short*)malloc(nr_samples);
397         out = outbuf = (unsigned short*)malloc(nr_samples);
398
399         r = image->comps[0].data;
400         g = image->comps[1].data;
401         b = image->comps[2].data;
402
403         for(i = 0; i < max; ++i)
404   {
405         *in++ = (unsigned short)*r++;
406         *in++ = (unsigned short)*g++;
407         *in++ = (unsigned short)*b++;
408   }
409
410         cmsDoTransform(transform, inbuf, outbuf, max);
411
412         r = image->comps[0].data;
413         g = image->comps[1].data;
414         b = image->comps[2].data;
415
416         for(i = 0; i < max; ++i)
417   {
418         *r++ = (int)*out++;
419         *g++ = (int)*out++;
420         *b++ = (int)*out++;
421   }
422         free(inbuf); free(outbuf);
423    }
424         else /* GRAY, GRAYA */
425    {
426         unsigned char *in, *inbuf, *out, *outbuf;
427
428         max = max_w * max_h; nr_samples = max * 3 * sizeof(unsigned char);
429         in = inbuf = (unsigned char*)malloc(nr_samples);
430         out = outbuf = (unsigned char*)malloc(nr_samples);
431
432         image->comps = (opj_image_comp_t*)
433          realloc(image->comps, (image->numcomps+2)*sizeof(opj_image_comp_t));
434
435         if(image->numcomps == 2)
436          image->comps[3] = image->comps[1];
437
438         image->comps[1] = image->comps[0];
439         image->comps[2] = image->comps[0];
440
441         image->comps[1].data = (int*)calloc(max, sizeof(int));
442         image->comps[2].data = (int*)calloc(max, sizeof(int));
443
444         image->numcomps += 2;
445
446         r = image->comps[0].data;
447
448         for(i = 0; i < max; ++i)
449   {
450         *in++ = (unsigned char)*r++;
451   }
452         cmsDoTransform(transform, inbuf, outbuf, max);
453
454         r = image->comps[0].data;
455         g = image->comps[1].data;
456         b = image->comps[2].data;
457
458         for(i = 0; i < max; ++i)
459   {
460         *r++ = (int)*out++; *g++ = (int)*out++; *b++ = (int)*out++;
461   }
462         free(inbuf); free(outbuf);
463
464    }/* if(image->numcomps */
465
466         cmsDeleteTransform(transform);
467
468 #ifdef OPJ_HAVE_LIBLCMS1
469         cmsCloseProfile(in_prof);
470         cmsCloseProfile(out_prof);
471 #endif
472 }/* color_apply_icc_profile() */
473
474 #endif /* OPJ_HAVE_LIBLCMS2 || OPJ_HAVE_LIBLCMS1 */
475