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