Merge pull request #706 from mayeut/issue135
[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         size_t maxw, maxh, max, i;
95         int offset, upb;
96
97         upb = (int)img->comps[0].prec;
98         offset = 1<<(upb - 1); upb = (1<<upb)-1;
99
100         maxw = (size_t)img->comps[0].w; maxh = (size_t)img->comps[0].h;
101         max = maxw * maxh;
102
103         y = img->comps[0].data;
104         cb = img->comps[1].data;
105         cr = img->comps[2].data;
106
107         d0 = r = (int*)malloc(sizeof(int) * max);
108         d1 = g = (int*)malloc(sizeof(int) * max);
109         d2 = b = (int*)malloc(sizeof(int) * max);
110
111         if(r == NULL || g == NULL || b == NULL) goto fails;
112
113         for(i = 0U; i < max; ++i)
114         {
115                 sycc_to_rgb(offset, upb, *y, *cb, *cr, r, g, b);
116                 ++y; ++cb; ++cr; ++r; ++g; ++b;
117         }
118         free(img->comps[0].data); img->comps[0].data = d0;
119         free(img->comps[1].data); img->comps[1].data = d1;
120         free(img->comps[2].data); img->comps[2].data = d2;
121         img->color_space = OPJ_CLRSPC_SRGB;
122         return;
123
124 fails:
125         free(r);
126         free(g);
127         free(b);
128 }/* sycc444_to_rgb() */
129
130 static void sycc422_to_rgb(opj_image_t *img)
131 {       
132         int *d0, *d1, *d2, *r, *g, *b;
133         const int *y, *cb, *cr;
134         size_t maxw, maxh, max, offx, loopmaxw;
135         int offset, upb;
136         size_t i;
137
138         upb = (int)img->comps[0].prec;
139         offset = 1<<(upb - 1); upb = (1<<upb)-1;
140
141         maxw = (size_t)img->comps[0].w; maxh = (size_t)img->comps[0].h;
142         max = maxw * maxh;
143
144         y = img->comps[0].data;
145         cb = img->comps[1].data;
146         cr = img->comps[2].data;
147
148         d0 = r = (int*)malloc(sizeof(int) * max);
149         d1 = g = (int*)malloc(sizeof(int) * max);
150         d2 = b = (int*)malloc(sizeof(int) * max);
151
152         if(r == NULL || g == NULL || b == NULL) goto fails;
153
154         /* if img->x0 is odd, then first column shall use Cb/Cr = 0 */
155         offx = img->x0 & 1U;
156         loopmaxw = maxw - offx;
157         
158         for(i=0U; i < maxh; ++i)
159         {
160                 size_t j;
161                 
162                 if (offx > 0U) {
163                         sycc_to_rgb(offset, upb, *y, 0, 0, r, g, b);
164                         ++y; ++r; ++g; ++b;
165                 }
166                 
167                 for(j=0U; j < (loopmaxw & ~(size_t)1U); j += 2U)
168                 {
169                         sycc_to_rgb(offset, upb, *y, *cb, *cr, r, g, b);
170                         ++y; ++r; ++g; ++b;
171                         sycc_to_rgb(offset, upb, *y, *cb, *cr, r, g, b);
172                         ++y; ++r; ++g; ++b; ++cb; ++cr;
173                 }
174                 if (j < loopmaxw) {
175                         sycc_to_rgb(offset, upb, *y, *cb, *cr, r, g, b);
176                         ++y; ++r; ++g; ++b; ++cb; ++cr;
177                 }
178         }
179         
180         free(img->comps[0].data); img->comps[0].data = d0;
181         free(img->comps[1].data); img->comps[1].data = d1;
182         free(img->comps[2].data); img->comps[2].data = d2;
183
184         img->comps[1].w = img->comps[2].w = img->comps[0].w;
185         img->comps[1].h = img->comps[2].h = img->comps[0].h;
186         img->comps[1].dx = img->comps[2].dx = img->comps[0].dx;
187         img->comps[1].dy = img->comps[2].dy = img->comps[0].dy;
188         img->color_space = OPJ_CLRSPC_SRGB;
189         return;
190
191 fails:
192         free(r);
193         free(g);
194         free(b);
195 }/* sycc422_to_rgb() */
196
197 static void sycc420_to_rgb(opj_image_t *img)
198 {
199         int *d0, *d1, *d2, *r, *g, *b, *nr, *ng, *nb;
200         const int *y, *cb, *cr, *ny;
201         size_t maxw, maxh, max, offx, loopmaxw, offy, loopmaxh;
202         int offset, upb;
203         size_t i;
204
205         upb = (int)img->comps[0].prec;
206         offset = 1<<(upb - 1); upb = (1<<upb)-1;
207
208         maxw = (size_t)img->comps[0].w; maxh = (size_t)img->comps[0].h;
209         max = maxw * maxh;
210
211         y = img->comps[0].data;
212         cb = img->comps[1].data;
213         cr = img->comps[2].data;
214
215         d0 = r = (int*)malloc(sizeof(int) * max);
216         d1 = g = (int*)malloc(sizeof(int) * max);
217         d2 = b = (int*)malloc(sizeof(int) * max);
218         
219         if (r == NULL || g == NULL || b == NULL) goto fails;
220         
221         /* if img->x0 is odd, then first column shall use Cb/Cr = 0 */
222         offx = img->x0 & 1U;
223         loopmaxw = maxw - offx;
224         /* if img->y0 is odd, then first line shall use Cb/Cr = 0 */
225         offy = img->y0 & 1U;
226         loopmaxh = maxh - offy;
227         
228         if (offy > 0U) {
229                 size_t j;
230                 
231                 for(j=0; j < maxw; ++j)
232                 {
233                         sycc_to_rgb(offset, upb, *y, 0, 0, r, g, b);
234                         ++y; ++r; ++g; ++b;
235                 }
236         }
237
238         for(i=0U; i < (loopmaxh & ~(size_t)1U); i += 2U)
239         {
240                 size_t j;
241                 
242                 ny = y + maxw;
243                 nr = r + maxw; ng = g + maxw; nb = b + maxw;
244                 
245                 if (offx > 0U) {
246                         sycc_to_rgb(offset, upb, *y, 0, 0, r, g, b);
247                         ++y; ++r; ++g; ++b;
248                         sycc_to_rgb(offset, upb, *ny, *cb, *cr, nr, ng, nb);
249                         ++ny; ++nr; ++ng; ++nb;
250                 }
251
252                 for(j=0; j < (loopmaxw & ~(size_t)1U); j += 2U)
253                 {
254                         sycc_to_rgb(offset, upb, *y, *cb, *cr, r, g, b);
255                         ++y; ++r; ++g; ++b;
256                         sycc_to_rgb(offset, upb, *y, *cb, *cr, r, g, b);
257                         ++y; ++r; ++g; ++b;
258
259                         sycc_to_rgb(offset, upb, *ny, *cb, *cr, nr, ng, nb);
260                         ++ny; ++nr; ++ng; ++nb;
261                         sycc_to_rgb(offset, upb, *ny, *cb, *cr, nr, ng, nb);
262                         ++ny; ++nr; ++ng; ++nb; ++cb; ++cr;
263                 }
264                 if(j < loopmaxw)
265                 {
266                         sycc_to_rgb(offset, upb, *y, *cb, *cr, r, g, b);
267                         ++y; ++r; ++g; ++b;
268
269                         sycc_to_rgb(offset, upb, *ny, *cb, *cr, nr, ng, nb);
270                         ++ny; ++nr; ++ng; ++nb; ++cb; ++cr;
271                 }
272                 y += maxw; r += maxw; g += maxw; b += maxw;
273         }
274         if(i < loopmaxh)
275         {
276                 size_t j;
277                 
278                 for(j=0U; j < (maxw & ~(size_t)1U); j += 2U)
279                 {
280                         sycc_to_rgb(offset, upb, *y, *cb, *cr, r, g, b);
281
282                         ++y; ++r; ++g; ++b;
283
284                         sycc_to_rgb(offset, upb, *y, *cb, *cr, r, g, b);
285
286                         ++y; ++r; ++g; ++b; ++cb; ++cr;
287                 }
288                 if(j < maxw)
289                 {
290                         sycc_to_rgb(offset, upb, *y, *cb, *cr, r, g, b);
291                 }
292         }
293
294         free(img->comps[0].data); img->comps[0].data = d0;
295         free(img->comps[1].data); img->comps[1].data = d1;
296         free(img->comps[2].data); img->comps[2].data = d2;
297
298         img->comps[1].w = img->comps[2].w = img->comps[0].w;
299         img->comps[1].h = img->comps[2].h = img->comps[0].h;
300         img->comps[1].dx = img->comps[2].dx = img->comps[0].dx;
301         img->comps[1].dy = img->comps[2].dy = img->comps[0].dy;
302         img->color_space = OPJ_CLRSPC_SRGB;
303         return;
304
305 fails:
306         free(r);
307         free(g);
308         free(b);
309 }/* sycc420_to_rgb() */
310
311 void color_sycc_to_rgb(opj_image_t *img)
312 {
313         if(img->numcomps < 3)
314         {
315                 img->color_space = OPJ_CLRSPC_GRAY;
316                 return;
317         }
318
319         if((img->comps[0].dx == 1)
320         && (img->comps[1].dx == 2)
321         && (img->comps[2].dx == 2)
322         && (img->comps[0].dy == 1)
323         && (img->comps[1].dy == 2)
324         && (img->comps[2].dy == 2))/* horizontal and vertical sub-sample */
325   {
326                 sycc420_to_rgb(img);
327   }
328         else
329         if((img->comps[0].dx == 1)
330         && (img->comps[1].dx == 2)
331         && (img->comps[2].dx == 2)
332         && (img->comps[0].dy == 1)
333         && (img->comps[1].dy == 1)
334         && (img->comps[2].dy == 1))/* horizontal sub-sample only */
335   {
336                 sycc422_to_rgb(img);
337   }
338         else
339         if((img->comps[0].dx == 1)
340         && (img->comps[1].dx == 1)
341         && (img->comps[2].dx == 1)
342         && (img->comps[0].dy == 1)
343         && (img->comps[1].dy == 1)
344         && (img->comps[2].dy == 1))/* no sub-sample */
345   {
346                 sycc444_to_rgb(img);
347   }
348         else
349   {
350                 fprintf(stderr,"%s:%d:color_sycc_to_rgb\n\tCAN NOT CONVERT\n", __FILE__,__LINE__);
351                 return;
352   }
353 }/* color_sycc_to_rgb() */
354
355 #if defined(OPJ_HAVE_LIBLCMS2) || defined(OPJ_HAVE_LIBLCMS1)
356
357 #ifdef OPJ_HAVE_LIBLCMS1
358 /* Bob Friesenhahn proposed:*/
359 #define cmsSigXYZData   icSigXYZData
360 #define cmsSigLabData   icSigLabData
361 #define cmsSigCmykData  icSigCmykData
362 #define cmsSigYCbCrData icSigYCbCrData
363 #define cmsSigLuvData   icSigLuvData
364 #define cmsSigGrayData  icSigGrayData
365 #define cmsSigRgbData   icSigRgbData
366 #define cmsUInt32Number DWORD
367
368 #define cmsColorSpaceSignature icColorSpaceSignature
369 #define cmsGetHeaderRenderingIntent cmsTakeRenderingIntent
370
371 #endif /* OPJ_HAVE_LIBLCMS1 */
372
373 /*#define DEBUG_PROFILE*/
374 void color_apply_icc_profile(opj_image_t *image)
375 {
376         cmsHPROFILE in_prof, out_prof;
377         cmsHTRANSFORM transform;
378         cmsColorSpaceSignature in_space, out_space;
379         cmsUInt32Number intent, in_type, out_type;
380         int *r, *g, *b;
381         size_t nr_samples, i, max, max_w, max_h;
382         int prec, ok = 0;
383         OPJ_COLOR_SPACE new_space;
384
385         in_prof = cmsOpenProfileFromMem(image->icc_profile_buf, image->icc_profile_len);
386 #ifdef DEBUG_PROFILE
387         FILE *icm = fopen("debug.icm","wb");
388         fwrite( image->icc_profile_buf,1, image->icc_profile_len,icm);
389         fclose(icm);
390 #endif
391
392         if(in_prof == NULL) return;
393
394         in_space = cmsGetPCS(in_prof);
395         out_space = cmsGetColorSpace(in_prof);
396         intent = cmsGetHeaderRenderingIntent(in_prof);
397
398         
399         max_w = image->comps[0].w;
400         max_h = image->comps[0].h;
401         prec = (int)image->comps[0].prec;
402
403         if(out_space == cmsSigRgbData) /* enumCS 16 */
404         {
405                 if( prec <= 8 )
406                 {
407                         in_type = TYPE_RGB_8;
408                         out_type = TYPE_RGB_8;
409                 }
410                 else
411                 {
412                         in_type = TYPE_RGB_16;
413                         out_type = TYPE_RGB_16;
414                 }
415                 out_prof = cmsCreate_sRGBProfile();
416                 new_space = OPJ_CLRSPC_SRGB;
417         }
418         else if(out_space == cmsSigGrayData) /* enumCS 17 */
419         {
420                 in_type = TYPE_GRAY_8;
421                 out_type = TYPE_RGB_8;
422                 out_prof = cmsCreate_sRGBProfile();
423                 new_space = OPJ_CLRSPC_SRGB;
424         }
425         else if(out_space == cmsSigYCbCrData) /* enumCS 18 */
426         {
427                 in_type = TYPE_YCbCr_16;
428                 out_type = TYPE_RGB_16;
429                 out_prof = cmsCreate_sRGBProfile();
430                 new_space = OPJ_CLRSPC_SRGB;
431         }
432         else
433         {
434 #ifdef DEBUG_PROFILE
435                 fprintf(stderr,"%s:%d: color_apply_icc_profile\n\tICC Profile has unknown "
436                         "output colorspace(%#x)(%c%c%c%c)\n\tICC Profile ignored.\n",
437                         __FILE__,__LINE__,out_space,
438                         (out_space>>24) & 0xff,(out_space>>16) & 0xff,
439                         (out_space>>8) & 0xff, out_space & 0xff);
440 #endif
441                 cmsCloseProfile(in_prof);
442
443                 return;
444         }
445         if(out_prof == NULL)
446         {
447                 cmsCloseProfile(in_prof);
448                 return;
449         }
450
451 #ifdef DEBUG_PROFILE
452         fprintf(stderr,"%s:%d:color_apply_icc_profile\n\tchannels(%d) prec(%d) w(%d) h(%d)"
453                 "\n\tprofile: in(%p) out(%p)\n",__FILE__,__LINE__,image->numcomps,prec,
454                 max_w,max_h, (void*)in_prof,(void*)out_prof);
455
456         fprintf(stderr,"\trender_intent (%u)\n\t"
457                 "color_space: in(%#x)(%c%c%c%c)   out:(%#x)(%c%c%c%c)\n\t"
458                 "       type: in(%u)              out:(%u)\n",
459                 intent,
460                 in_space,
461                 (in_space>>24) & 0xff,(in_space>>16) & 0xff,
462                 (in_space>>8) & 0xff, in_space & 0xff,
463
464                 out_space,
465                 (out_space>>24) & 0xff,(out_space>>16) & 0xff,
466                 (out_space>>8) & 0xff, out_space & 0xff,
467
468                 in_type,out_type
469         );
470 #else
471   (void)prec;
472   (void)in_space;
473 #endif /* DEBUG_PROFILE */
474
475         transform = cmsCreateTransform(in_prof, in_type, out_prof, out_type, intent, 0);
476
477 #ifdef OPJ_HAVE_LIBLCMS2
478 /* Possible for: LCMS_VERSION >= 2000 :*/
479         cmsCloseProfile(in_prof);
480         cmsCloseProfile(out_prof);
481 #endif
482
483         if(transform == NULL)
484         {
485 #ifdef DEBUG_PROFILE
486                 fprintf(stderr,"%s:%d:color_apply_icc_profile\n\tcmsCreateTransform failed. "
487                         "ICC Profile ignored.\n",__FILE__,__LINE__);
488 #endif
489
490 #ifdef OPJ_HAVE_LIBLCMS1
491                 cmsCloseProfile(in_prof);
492                 cmsCloseProfile(out_prof);
493 #endif
494                 return;
495         }
496
497         if(image->numcomps > 2)/* RGB, RGBA */
498         {
499                 if( prec <= 8 )
500                 {
501                         unsigned char *inbuf, *outbuf, *in, *out;
502
503                         max = max_w * max_h;
504                         nr_samples = (size_t)(max * 3U * sizeof(unsigned char));
505                         in = inbuf = (unsigned char*)malloc(nr_samples);
506                         out = outbuf = (unsigned char*)malloc(nr_samples);
507
508                         if(inbuf == NULL || outbuf == NULL) goto fails0;
509
510                         r = image->comps[0].data;
511                         g = image->comps[1].data;
512                         b = image->comps[2].data;
513
514                         for(i = 0U; i < max; ++i)
515                         {
516                                 *in++ = (unsigned char)*r++;
517                                 *in++ = (unsigned char)*g++;
518                                 *in++ = (unsigned char)*b++;
519                         }
520
521                         cmsDoTransform(transform, inbuf, outbuf, (cmsUInt32Number)max);
522
523                         r = image->comps[0].data;
524                         g = image->comps[1].data;
525                         b = image->comps[2].data;
526
527                         for(i = 0U; i < max; ++i)
528                         {
529                                 *r++ = (int)*out++;
530                                 *g++ = (int)*out++;
531                                 *b++ = (int)*out++;
532                         }
533                         ok = 1;
534
535 fails0:
536                         free(inbuf);
537                         free(outbuf);
538                 }
539                 else /* prec > 8 */
540                 {
541                         unsigned short *inbuf, *outbuf, *in, *out;
542
543                         max = max_w * max_h;
544                         nr_samples = (size_t)(max * 3U * sizeof(unsigned short));
545                         in = inbuf = (unsigned short*)malloc(nr_samples);
546                         out = outbuf = (unsigned short*)malloc(nr_samples);
547
548                         if(inbuf == NULL || outbuf == NULL) goto fails1;
549
550                         r = image->comps[0].data;
551                         g = image->comps[1].data;
552                         b = image->comps[2].data;
553
554                         for(i = 0U      ; i < max; ++i)
555                         {
556                                 *in++ = (unsigned short)*r++;
557                                 *in++ = (unsigned short)*g++;
558                                 *in++ = (unsigned short)*b++;
559                         }
560
561                         cmsDoTransform(transform, inbuf, outbuf, (cmsUInt32Number)max);
562
563                         r = image->comps[0].data;
564                         g = image->comps[1].data;
565                         b = image->comps[2].data;
566
567                         for(i = 0; i < max; ++i)
568                         {
569                                 *r++ = (int)*out++;
570                                 *g++ = (int)*out++;
571                                 *b++ = (int)*out++;
572                         }
573                         ok = 1;
574
575 fails1:
576                         free(inbuf);
577                         free(outbuf);
578                 }
579         }
580         else /* image->numcomps <= 2 : GRAY, GRAYA */
581         {
582                 if(prec <= 8)
583                 {
584                         unsigned char *in, *inbuf, *out, *outbuf;
585                         opj_image_comp_t *new_comps;
586
587                         max = max_w * max_h;
588                         nr_samples = (size_t)(max * 3 * sizeof(unsigned char));
589                         in = inbuf = (unsigned char*)malloc(nr_samples);
590                         out = outbuf = (unsigned char*)malloc(nr_samples);
591                         g = (int*)calloc((size_t)max, sizeof(int));
592                         b = (int*)calloc((size_t)max, sizeof(int));
593
594                         if(inbuf == NULL || outbuf == NULL || g == NULL || b == NULL) goto fails2;
595
596                         new_comps = (opj_image_comp_t*)realloc(image->comps, (image->numcomps+2)*sizeof(opj_image_comp_t));
597
598                         if(new_comps == NULL) goto fails2;
599
600                         image->comps = new_comps;
601
602                         if(image->numcomps == 2)
603                                 image->comps[3] = image->comps[1];
604
605                         image->comps[1] = image->comps[0];
606                         image->comps[2] = image->comps[0];
607
608                         image->comps[1].data = g;
609                         image->comps[2].data = b;
610
611                         image->numcomps += 2;
612
613                         r = image->comps[0].data;
614
615                         for(i = 0U; i < max; ++i)
616                         {
617                                 *in++ = (unsigned char)*r++;
618                         }
619                         cmsDoTransform(transform, inbuf, outbuf, (cmsUInt32Number)max);
620
621                         r = image->comps[0].data;
622                         g = image->comps[1].data;
623                         b = image->comps[2].data;
624
625                         for(i = 0U; i < max; ++i)
626                         {
627                                 *r++ = (int)*out++; *g++ = (int)*out++; *b++ = (int)*out++;
628                         }
629                         r = g = b = NULL;
630                         ok = 1;
631
632 fails2:
633                         free(inbuf);
634                         free(outbuf);
635                         free(g);
636                         free(b);
637                 }
638                 else /* prec > 8 */
639                 {
640                         unsigned short *in, *inbuf, *out, *outbuf;
641                         opj_image_comp_t *new_comps;
642
643                         max = max_w * max_h;
644                         nr_samples = (size_t)(max * 3U * sizeof(unsigned short));
645                         in = inbuf = (unsigned short*)malloc(nr_samples);
646                         out = outbuf = (unsigned short*)malloc(nr_samples);
647                         g = (int*)calloc((size_t)max, sizeof(int));
648                         b = (int*)calloc((size_t)max, sizeof(int));
649
650                         if(inbuf == NULL || outbuf == NULL || g == NULL || b == NULL) goto fails3;
651
652                         new_comps = (opj_image_comp_t*)realloc(image->comps, (image->numcomps+2)*sizeof(opj_image_comp_t));
653
654                         if(new_comps == NULL) goto fails3;
655
656                         image->comps = new_comps;
657
658                         if(image->numcomps == 2)
659                                 image->comps[3] = image->comps[1];
660
661                         image->comps[1] = image->comps[0];
662                         image->comps[2] = image->comps[0];
663
664                         image->comps[1].data = g;
665                         image->comps[2].data = b;
666
667                         image->numcomps += 2;
668
669                         r = image->comps[0].data;
670
671                         for(i = 0U; i < max; ++i)
672                         {
673                                 *in++ = (unsigned short)*r++;
674                         }
675                         cmsDoTransform(transform, inbuf, outbuf, (cmsUInt32Number)max);
676
677                         r = image->comps[0].data;
678                         g = image->comps[1].data;
679                         b = image->comps[2].data;
680
681                         for(i = 0; i < max; ++i)
682                         {
683                                 *r++ = (int)*out++; *g++ = (int)*out++; *b++ = (int)*out++;
684                         }
685                         r = g = b = NULL;
686                         ok = 1;
687
688 fails3:
689                         free(inbuf);
690                         free(outbuf);
691                         free(g);
692                         free(b);
693                 }
694         }/* if(image->numcomps > 2) */
695
696         cmsDeleteTransform(transform);
697
698 #ifdef OPJ_HAVE_LIBLCMS1
699         cmsCloseProfile(in_prof);
700         cmsCloseProfile(out_prof);
701 #endif
702         if(ok)
703         {
704                 image->color_space = new_space;
705         }
706 }/* color_apply_icc_profile() */
707
708 void color_cielab_to_rgb(opj_image_t *image)
709 {
710         int *row;
711         int enumcs, numcomps;
712         OPJ_COLOR_SPACE new_space;
713
714         numcomps = (int)image->numcomps;
715         
716         if(numcomps != 3)
717         {
718                 fprintf(stderr,"%s:%d:\n\tnumcomps %d not handled. Quitting.\n",
719                                                 __FILE__,__LINE__,numcomps);
720                 return;
721         }
722         
723         row = (int*)image->icc_profile_buf;
724         enumcs = row[0];
725         
726         if(enumcs == 14) /* CIELab */
727         {
728                 int *L, *a, *b, *red, *green, *blue;
729                 int *src0, *src1, *src2, *dst0, *dst1, *dst2;
730                 double rl, ol, ra, oa, rb, ob, prec0, prec1, prec2;
731                 double minL, maxL, mina, maxa, minb, maxb;
732                 unsigned int default_type;
733                 unsigned int i, max;
734                 cmsHPROFILE in, out;
735                 cmsHTRANSFORM transform;
736                 cmsUInt16Number RGB[3];
737                 cmsCIELab Lab;
738                 
739                 in = cmsCreateLab4Profile(NULL);
740                 if(in == NULL){
741                         return;
742                 }
743                 out = cmsCreate_sRGBProfile();
744                 if(out == NULL){
745                         cmsCloseProfile(in);
746                         return;
747                 }
748                 transform = cmsCreateTransform(in, TYPE_Lab_DBL, out, TYPE_RGB_16, INTENT_PERCEPTUAL, 0);
749                 
750 #ifdef OPJ_HAVE_LIBLCMS2
751                 cmsCloseProfile(in);
752                 cmsCloseProfile(out);
753 #endif
754                 if(transform == NULL)
755                 {
756 #ifdef OPJ_HAVE_LIBLCMS1
757                         cmsCloseProfile(in);
758                         cmsCloseProfile(out);
759 #endif
760                         return;
761                 }
762                 new_space = OPJ_CLRSPC_SRGB;
763
764                 prec0 = (double)image->comps[0].prec;
765                 prec1 = (double)image->comps[1].prec;
766                 prec2 = (double)image->comps[2].prec;
767                 
768                 default_type = (unsigned int)row[1];
769                 
770                 if(default_type == 0x44454600)/* DEF : default */
771                 {
772                         rl = 100; ra = 170; rb = 200;
773                         ol = 0;
774                         oa = pow(2, prec1 - 1);
775                         ob = pow(2, prec2 - 2) +  pow(2, prec2 - 3);
776                 }
777                 else
778                 {
779                         rl = row[2]; ra = row[4]; rb = row[6];
780                         ol = row[3]; oa = row[5]; ob = row[7];
781                 }
782                 
783                 L = src0 = image->comps[0].data;
784                 a = src1 = image->comps[1].data;
785                 b = src2 = image->comps[2].data;
786                 
787                 max = image->comps[0].w * image->comps[0].h;
788                 
789                 red = dst0 = (int*)malloc(max * sizeof(int));
790                 green = dst1 = (int*)malloc(max * sizeof(int));
791                 blue = dst2 = (int*)malloc(max * sizeof(int));
792
793                 if(red == NULL || green == NULL || blue == NULL) goto fails;
794
795                 minL = -(rl * ol)/(pow(2, prec0)-1);
796                 maxL = minL + rl;
797                 
798                 mina = -(ra * oa)/(pow(2, prec1)-1);
799                 maxa = mina + ra;
800                 
801                 minb = -(rb * ob)/(pow(2, prec2)-1);
802                 maxb = minb + rb;
803                 
804                 for(i = 0; i < max; ++i)
805                 {
806                         Lab.L = minL + (double)(*L) * (maxL - minL)/(pow(2, prec0)-1); ++L;
807                         Lab.a = mina + (double)(*a) * (maxa - mina)/(pow(2, prec1)-1); ++a;
808                         Lab.b = minb + (double)(*b) * (maxb - minb)/(pow(2, prec2)-1); ++b;
809                 
810                         cmsDoTransform(transform, &Lab, RGB, 1);
811                 
812                         *red++ = RGB[0];
813                         *green++ = RGB[1];
814                         *blue++ = RGB[2];
815                 }
816                 cmsDeleteTransform(transform);
817 #ifdef OPJ_HAVE_LIBLCMS1
818                 cmsCloseProfile(in);
819                 cmsCloseProfile(out);
820 #endif
821                 free(src0); image->comps[0].data = dst0;
822                 free(src1); image->comps[1].data = dst1;
823                 free(src2); image->comps[2].data = dst2;
824                 
825                 image->color_space = new_space;
826                 image->comps[0].prec = 16;
827                 image->comps[1].prec = 16;
828                 image->comps[2].prec = 16;
829                 
830                 return;
831
832 fails:
833                 cmsDeleteTransform(transform);
834 #ifdef OPJ_HAVE_LIBLCMS1
835                 cmsCloseProfile(in);
836                 cmsCloseProfile(out);
837 #endif
838                 if(red) free(red);
839                 if(green) free(green);
840                 if(blue) free(blue);
841                 return;
842         }
843         
844         fprintf(stderr,"%s:%d:\n\tenumCS %d not handled. Ignoring.\n", __FILE__,__LINE__, enumcs);
845 }/* color_cielab_to_rgb() */
846
847 #endif /* OPJ_HAVE_LIBLCMS2 || OPJ_HAVE_LIBLCMS1 */
848
849 void color_cmyk_to_rgb(opj_image_t *image)
850 {
851         float C, M, Y, K;
852         float sC, sM, sY, sK;
853         unsigned int w, h, max, i;
854
855         w = image->comps[0].w;
856         h = image->comps[0].h;
857
858         if(image->numcomps < 4) return;
859
860         max = w * h;
861         
862         sC = 1.0F / (float)((1 << image->comps[0].prec) - 1);
863         sM = 1.0F / (float)((1 << image->comps[1].prec) - 1);
864         sY = 1.0F / (float)((1 << image->comps[2].prec) - 1);
865         sK = 1.0F / (float)((1 << image->comps[3].prec) - 1);
866
867         for(i = 0; i < max; ++i)
868         {
869                 /* CMYK values from 0 to 1 */
870                 C = (float)(image->comps[0].data[i]) * sC;
871                 M = (float)(image->comps[1].data[i]) * sM;
872                 Y = (float)(image->comps[2].data[i]) * sY;
873                 K = (float)(image->comps[3].data[i]) * sK;
874                 
875                 /* Invert all CMYK values */
876                 C = 1.0F - C;
877                 M = 1.0F - M;
878                 Y = 1.0F - Y;
879                 K = 1.0F - K;
880
881                 /* CMYK -> RGB : RGB results from 0 to 255 */
882                 image->comps[0].data[i] = (int)(255.0F * C * K); /* R */
883                 image->comps[1].data[i] = (int)(255.0F * M * K); /* G */
884                 image->comps[2].data[i] = (int)(255.0F * Y * K); /* B */
885         }
886
887         free(image->comps[3].data); image->comps[3].data = NULL;
888         image->comps[0].prec = 8;
889         image->comps[1].prec = 8;
890         image->comps[2].prec = 8;
891         image->numcomps -= 1;
892         image->color_space = OPJ_CLRSPC_SRGB;
893         
894         for (i = 3; i < image->numcomps; ++i) {
895                 memcpy(&(image->comps[i]), &(image->comps[i+1]), sizeof(image->comps[i]));
896         }
897
898 }/* color_cmyk_to_rgb() */
899
900 /*
901  * This code has been adopted from sjpx_openjpeg.c of ghostscript
902  */
903 void color_esycc_to_rgb(opj_image_t *image)
904 {
905         int y, cb, cr, sign1, sign2, val;
906         unsigned int w, h, max, i;
907         int flip_value = (1 << (image->comps[0].prec-1));
908         int max_value = (1 << image->comps[0].prec) - 1;
909         
910         if (
911                     (image->numcomps < 3)
912                  || (image->comps[0].dx != image->comps[1].dx) || (image->comps[0].dx != image->comps[2].dx)
913                  || (image->comps[0].dy != image->comps[1].dy) || (image->comps[0].dy != image->comps[2].dy)
914            ) {
915                 fprintf(stderr,"%s:%d:color_esycc_to_rgb\n\tCAN NOT CONVERT\n", __FILE__,__LINE__);
916                 return;
917         }
918         
919         w = image->comps[0].w;
920         h = image->comps[0].h;
921         
922         sign1 = (int)image->comps[1].sgnd;
923         sign2 = (int)image->comps[2].sgnd;
924         
925         max = w * h;
926         
927         for(i = 0; i < max; ++i)
928         {
929                 
930                 y = image->comps[0].data[i]; cb = image->comps[1].data[i]; cr = image->comps[2].data[i];
931                 
932                 if( !sign1) cb -= flip_value;
933                 if( !sign2) cr -= flip_value;
934                 
935                 val = (int)
936                 ((float)y - (float)0.0000368 * (float)cb
937                  + (float)1.40199 * (float)cr + (float)0.5);
938                 
939                 if(val > max_value) val = max_value; else if(val < 0) val = 0;
940                 image->comps[0].data[i] = val;
941                 
942                 val = (int)
943                 ((float)1.0003 * (float)y - (float)0.344125 * (float)cb
944                  - (float)0.7141128 * (float)cr + (float)0.5);
945                 
946                 if(val > max_value) val = max_value; else if(val < 0) val = 0;
947                 image->comps[1].data[i] = val;
948                 
949                 val = (int)
950                 ((float)0.999823 * (float)y + (float)1.77204 * (float)cb
951                  - (float)0.000008 *(float)cr + (float)0.5);
952                 
953                 if(val > max_value) val = max_value; else if(val < 0) val = 0;
954                 image->comps[2].data[i] = val;
955         }
956         image->color_space = OPJ_CLRSPC_SRGB;
957
958 }/* color_esycc_to_rgb() */