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