[2.0] Backport all changes since r2798 (included) from trunk
[openjpeg.git] / src / bin / common / color.c
1 /*
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.
6  *
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.
15  *
16  * Redistribution and use in source and binary forms, with or without
17  * modification, are permitted provided that the following conditions
18  * are met:
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.
24  *
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.
36  */
37
38 #include <stdio.h>
39 #include <string.h>
40 #include <stdlib.h>
41 #include <math.h>
42 #include <assert.h>
43
44 #include "opj_apps_config.h"
45 #include "openjpeg.h"
46 #include "color.h"
47
48 #ifdef OPJ_HAVE_LIBLCMS2
49 #include <lcms2.h>
50 #endif
51 #ifdef OPJ_HAVE_LIBLCMS1
52 #include <lcms.h>
53 #endif
54
55 #ifdef OPJ_USE_LEGACY
56 #define OPJ_CLRSPC_GRAY CLRSPC_GRAY
57 #define OPJ_CLRSPC_SRGB CLRSPC_SRGB
58 #endif
59
60 /*--------------------------------------------------------
61 Matrix for sYCC, Amendment 1 to IEC 61966-2-1
62
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
66
67 Inverse:
68
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)
72
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)
76 {
77         int r, g, b;
78
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;
82
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;
85
86         b = y + (int)(1.772 * (float)cb);
87         if(b < 0) b = 0; else if(b > upb) b = upb; *out_b = b;
88 }
89
90 static void sycc444_to_rgb(opj_image_t *img)
91 {
92         int *d0, *d1, *d2, *r, *g, *b;
93         const int *y, *cb, *cr;
94         int maxw, maxh, max, i, offset, upb;
95
96         i = (int)img->comps[0].prec;
97         offset = 1<<(i - 1); upb = (1<<i)-1;
98
99         maxw = (int)img->comps[0].w; maxh = (int)img->comps[0].h;
100         max = maxw * maxh;
101
102         y = img->comps[0].data;
103         cb = img->comps[1].data;
104         cr = img->comps[2].data;
105
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);
109
110         for(i = 0; i < max; ++i)
111    {
112         sycc_to_rgb(offset, upb, *y, *cb, *cr, r, g, b);        
113
114         ++y; ++cb; ++cr; ++r; ++g; ++b;
115    }    
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;
119
120 }/* sycc444_to_rgb() */
121
122 static void sycc422_to_rgb(opj_image_t *img)
123 {       
124         int *d0, *d1, *d2, *r, *g, *b;
125         const int *y, *cb, *cr;
126         int maxw, maxh, max, offset, upb;
127         int i, j;
128
129         i = (int)img->comps[0].prec;
130         offset = 1<<(i - 1); upb = (1<<i)-1;
131
132         maxw = (int)img->comps[0].w; maxh = (int)img->comps[0].h;
133         max = maxw * maxh;
134
135         y = img->comps[0].data;
136         cb = img->comps[1].data;
137         cr = img->comps[2].data;
138
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);
142
143         for(i=0; i < maxh; ++i)
144    {
145         for(j=0; j < maxw; j += 2)
146   {
147         sycc_to_rgb(offset, upb, *y, *cb, *cr, r, g, b);
148
149         ++y; ++r; ++g; ++b;
150
151         sycc_to_rgb(offset, upb, *y, *cb, *cr, r, g, b);
152
153         ++y; ++r; ++g; ++b; ++cb; ++cr;
154   }
155    }
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;
159
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;
163 #else
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;
166 #endif
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;
171
172 }/* sycc422_to_rgb() */
173
174 static void sycc420_to_rgb(opj_image_t *img)
175 {
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;
179         int i, j;
180
181         i = (int)img->comps[0].prec;
182         offset = 1<<(i - 1); upb = (1<<i)-1;
183
184         maxw = (int)img->comps[0].w; maxh = (int)img->comps[0].h;
185         max = maxw * maxh;
186
187         y = img->comps[0].data;
188         cb = img->comps[1].data;
189         cr = img->comps[2].data;
190
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);
194
195         for(i=0; i < maxh; i += 2)
196    {
197         ny = y + maxw;
198         nr = r + maxw; ng = g + maxw; nb = b + maxw;
199
200         for(j=0; j < maxw;  j += 2)
201   {
202         sycc_to_rgb(offset, upb, *y, *cb, *cr, r, g, b);
203
204         ++y; ++r; ++g; ++b;
205
206         sycc_to_rgb(offset, upb, *y, *cb, *cr, r, g, b);
207
208         ++y; ++r; ++g; ++b;
209
210         sycc_to_rgb(offset, upb, *ny, *cb, *cr, nr, ng, nb);
211
212         ++ny; ++nr; ++ng; ++nb;
213
214         sycc_to_rgb(offset, upb, *ny, *cb, *cr, nr, ng, nb);
215
216         ++ny; ++nr; ++ng; ++nb; ++cb; ++cr;
217   }
218         y += maxw; r += maxw; g += maxw; b += maxw;
219    }
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;
223
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;
227 #else
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;
230 #endif
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;
235
236 }/* sycc420_to_rgb() */
237
238 void color_sycc_to_rgb(opj_image_t *img)
239 {
240         if(img->numcomps < 3) 
241    {
242         img->color_space = OPJ_CLRSPC_GRAY;
243         return;
244    }
245
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 */
252   {
253         sycc420_to_rgb(img);
254   }
255         else
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 */
262   {
263         sycc422_to_rgb(img);
264   }
265         else
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 */
272   {
273         sycc444_to_rgb(img);
274   }
275         else
276   {
277         fprintf(stderr,"%s:%d:color_sycc_to_rgb\n\tCAN NOT CONVERT\n",
278          __FILE__,__LINE__);
279         return;
280   }
281         img->color_space = OPJ_CLRSPC_SRGB;
282
283 }/* color_sycc_to_rgb() */
284
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
296
297 #define cmsColorSpaceSignature icColorSpaceSignature
298 #define cmsGetHeaderRenderingIntent cmsTakeRenderingIntent
299
300 #endif /* OPJ_HAVE_LIBLCMS1 */
301
302 /*#define DEBUG_PROFILE*/
303 void color_apply_icc_profile(opj_image_t *image)
304 {
305         cmsHPROFILE in_prof, out_prof;
306         cmsHTRANSFORM transform;
307         cmsColorSpaceSignature in_space, out_space;
308         cmsUInt32Number intent, in_type, out_type, nr_samples;
309         int *r, *g, *b;
310         int prec, i, max, max_w, max_h;
311         OPJ_COLOR_SPACE oldspace;
312
313         in_prof = 
314          cmsOpenProfileFromMem(image->icc_profile_buf, image->icc_profile_len);
315 #ifdef DEBUG_PROFILE
316   FILE *icm = fopen("debug.icm","wb");
317   fwrite( image->icc_profile_buf,1, image->icc_profile_len,icm);
318   fclose(icm);
319 #endif
320
321         if(in_prof == NULL) return;
322
323         in_space = cmsGetPCS(in_prof);
324         out_space = cmsGetColorSpace(in_prof);
325         intent = cmsGetHeaderRenderingIntent(in_prof);
326
327         
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;
332
333         if(out_space == cmsSigRgbData) /* enumCS 16 */
334    {
335   if( prec <= 8 )
336 {
337         in_type = TYPE_RGB_8;
338         out_type = TYPE_RGB_8;
339 }
340 else
341 {
342         in_type = TYPE_RGB_16;
343         out_type = TYPE_RGB_16;
344 }
345         out_prof = cmsCreate_sRGBProfile();
346         image->color_space = OPJ_CLRSPC_SRGB;
347    }
348         else
349         if(out_space == cmsSigGrayData) /* enumCS 17 */
350    {
351         in_type = TYPE_GRAY_8;
352         out_type = TYPE_RGB_8;
353         out_prof = cmsCreate_sRGBProfile();
354         image->color_space = OPJ_CLRSPC_SRGB;
355    }
356         else
357         if(out_space == cmsSigYCbCrData) /* enumCS 18 */
358    {
359         in_type = TYPE_YCbCr_16;
360         out_type = TYPE_RGB_16;
361         out_prof = cmsCreate_sRGBProfile();
362         image->color_space = OPJ_CLRSPC_SRGB;
363    }
364         else
365    {
366 #ifdef DEBUG_PROFILE
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);
372 #endif
373         return;
374    }
375
376 #ifdef DEBUG_PROFILE
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);
380
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",
384 intent,
385 in_space,
386 (in_space>>24) & 0xff,(in_space>>16) & 0xff,
387 (in_space>>8) & 0xff, in_space & 0xff,
388
389 out_space,
390 (out_space>>24) & 0xff,(out_space>>16) & 0xff,
391 (out_space>>8) & 0xff, out_space & 0xff,
392
393 in_type,out_type
394  );
395 #else
396   (void)prec;
397   (void)in_space;
398 #endif /* DEBUG_PROFILE */
399
400         transform = cmsCreateTransform(in_prof, in_type,
401          out_prof, out_type, intent, 0);
402
403 #ifdef OPJ_HAVE_LIBLCMS2
404 /* Possible for: LCMS_VERSION >= 2000 :*/
405         cmsCloseProfile(in_prof);
406         cmsCloseProfile(out_prof);
407 #endif
408
409         if(transform == NULL)
410    {
411 #ifdef DEBUG_PROFILE
412 fprintf(stderr,"%s:%d:color_apply_icc_profile\n\tcmsCreateTransform failed. "
413 "ICC Profile ignored.\n",__FILE__,__LINE__);
414 #endif
415         image->color_space = oldspace;
416 #ifdef OPJ_HAVE_LIBLCMS1
417         cmsCloseProfile(in_prof);
418         cmsCloseProfile(out_prof);
419 #endif
420         return;
421    }
422
423         if(image->numcomps > 2)/* RGB, RGBA */
424    {
425   if( prec <= 8 )
426 {
427         unsigned char *inbuf, *outbuf, *in, *out;
428         max = max_w * max_h;
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);
432
433         r = image->comps[0].data;
434         g = image->comps[1].data;
435         b = image->comps[2].data;
436
437         for(i = 0; i < max; ++i)
438   {
439         *in++ = (unsigned char)*r++;
440         *in++ = (unsigned char)*g++;
441         *in++ = (unsigned char)*b++;
442   }
443
444         cmsDoTransform(transform, inbuf, outbuf, (cmsUInt32Number)max);
445
446         r = image->comps[0].data;
447         g = image->comps[1].data;
448         b = image->comps[2].data;
449
450         for(i = 0; i < max; ++i)
451   {
452         *r++ = (int)*out++;
453         *g++ = (int)*out++;
454         *b++ = (int)*out++;
455   }
456         free(inbuf); free(outbuf);
457 }
458 else
459 {
460         unsigned short *inbuf, *outbuf, *in, *out;
461         max = max_w * max_h;
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);
465
466         r = image->comps[0].data;
467         g = image->comps[1].data;
468         b = image->comps[2].data;
469
470         for(i = 0; i < max; ++i)
471   {
472         *in++ = (unsigned short)*r++;
473         *in++ = (unsigned short)*g++;
474         *in++ = (unsigned short)*b++;
475   }
476
477         cmsDoTransform(transform, inbuf, outbuf, (cmsUInt32Number)max);
478
479         r = image->comps[0].data;
480         g = image->comps[1].data;
481         b = image->comps[2].data;
482
483         for(i = 0; i < max; ++i)
484   {
485         *r++ = (int)*out++;
486         *g++ = (int)*out++;
487         *b++ = (int)*out++;
488   }
489         free(inbuf); free(outbuf);
490 }
491    }
492         else /* GRAY, GRAYA */
493    {
494         unsigned char *in, *inbuf, *out, *outbuf;
495   max = max_w * max_h;
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);
499
500         image->comps = (opj_image_comp_t*)
501          realloc(image->comps, (image->numcomps+2)*sizeof(opj_image_comp_t));
502
503         if(image->numcomps == 2)
504          image->comps[3] = image->comps[1];
505
506         image->comps[1] = image->comps[0];
507         image->comps[2] = image->comps[0];
508
509         image->comps[1].data = (int*)calloc((size_t)max, sizeof(int));
510         image->comps[2].data = (int*)calloc((size_t)max, sizeof(int));
511
512         image->numcomps += 2;
513
514         r = image->comps[0].data;
515
516         for(i = 0; i < max; ++i)
517   {
518         *in++ = (unsigned char)*r++;
519   }
520         cmsDoTransform(transform, inbuf, outbuf, (cmsUInt32Number)max);
521
522         r = image->comps[0].data;
523         g = image->comps[1].data;
524         b = image->comps[2].data;
525
526         for(i = 0; i < max; ++i)
527   {
528         *r++ = (int)*out++; *g++ = (int)*out++; *b++ = (int)*out++;
529   }
530         free(inbuf); free(outbuf);
531
532    }/* if(image->numcomps */
533
534         cmsDeleteTransform(transform);
535
536 #ifdef OPJ_HAVE_LIBLCMS1
537         cmsCloseProfile(in_prof);
538         cmsCloseProfile(out_prof);
539 #endif
540 }/* color_apply_icc_profile() */
541
542 #endif /* OPJ_HAVE_LIBLCMS2 || OPJ_HAVE_LIBLCMS1 */
543