Engauge Digitizer 2
Loading...
Searching...
No Matches
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 -----------------------------------------------------------*/
66void 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
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
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
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
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 {
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 {
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 {
273 }
274 else
275 {
276 fprintf(stderr,"%s:%d:color_sycc_to_rgb\n\tCAN NOT CONVERT\n",
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
303{
308 int *r, *g, *b;
309 int prec, i, max, max_w, max_h;
311
312 in_prof =
313 cmsOpenProfileFromMem(image->icc_profile_buf, image->icc_profile_len);
314
315 if(in_prof == nullptr) return;
316
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 {
333 }
334 else
335 {
338 }
340 image->color_space = OPJ_CLRSPC_SRGB;
341 }
342 else
343 if(out_space == cmsSigGrayData) /* enumCS 17 */
344 {
348 image->color_space = OPJ_CLRSPC_SRGB;
349 }
350 else
351 if(out_space == cmsSigYCbCrData) /* enumCS 18 */
352 {
356 image->color_space = OPJ_CLRSPC_SRGB;
357 }
358 else
359 {
360 return;
361 }
362
363 (void)prec;
364 (void)in_space;
365
368
369#ifdef OPJ_HAVE_LIBLCMS2
370 /* Possible for: LCMS_VERSION >= 2000 :*/
373#endif
374
375 if(transform == nullptr)
376 {
377 image->color_space = oldspace;
378#ifdef OPJ_HAVE_LIBLCMS1
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
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 }
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
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 }
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 }
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 }
495
496 }/* if(image->numcomps */
497
499
500#ifdef OPJ_HAVE_LIBLCMS1
503#endif
504}/* color_apply_icc_profile() */
505
506#endif /* OPJ_HAVE_LIBLCMS2 || OPJ_HAVE_LIBLCMS1 */
const int INNER_RADIUS_MIN
void sycc_to_rgb(int offset, int upb, int y, int cb, int cr, int *out_r, int *out_g, int *out_b)
void color_sycc_to_rgb(opj_image_t *img)
void sycc420_to_rgb(opj_image_t *img)
void sycc444_to_rgb(opj_image_t *img)
void sycc422_to_rgb(opj_image_t *img)
void color_apply_icc_profile(opj_image_t *image)