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