Ansel 0.0
A darktable fork - bloat + design vision
Loading...
Searching...
No Matches
imageio_j2k.c
Go to the documentation of this file.
1/*
2 This file is part of darktable,
3 Copyright (C) 2012 Moritz Lipp.
4 Copyright (C) 2012-2014, 2016-2017 Tobias Ellinghaus.
5 Copyright (C) 2014 johannes hanika.
6 Copyright (C) 2014, 2016 Roman Lebedev.
7 Copyright (C) 2014 Ulrich Pegelow.
8 Copyright (C) 2020 Heiko Bauke.
9 Copyright (C) 2020-2021 Pascal Obry.
10 Copyright (C) 2021 François Guerraz.
11 Copyright (C) 2021 Miloš Komarčević.
12 Copyright (C) 2022 Martin Bařinka.
13 Copyright (C) 2023 Alynx Zhou.
14
15 darktable is free software: you can redistribute it and/or modify
16 it under the terms of the GNU General Public License as published by
17 the Free Software Foundation, either version 3 of the License, or
18 (at your option) any later version.
19
20 darktable is distributed in the hope that it will be useful,
21 but WITHOUT ANY WARRANTY; without even the implied warranty of
22 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
23 GNU General Public License for more details.
24
25 You should have received a copy of the GNU General Public License
26 along with darktable. If not, see <http://www.gnu.org/licenses/>.
27*/
28#ifdef HAVE_CONFIG_H
29#include "config.h"
30#endif
31#include "common/darktable.h"
32#include "common/exif.h"
33#include "common/imageio_j2k.h"
34#include "develop/imageop.h" // for IOP_CS_RGB
35
36#include <assert.h>
37#include <math.h>
38#include <stdio.h>
39#include <stdlib.h>
40#include <string.h>
41#include <strings.h>
42
43#if defined(__has_include)
44#if __has_include(<openjpeg.h>)
45#include <openjpeg.h>
46#elif __has_include(<openjpeg-2.5/openjpeg.h>)
47#include <openjpeg-2.5/openjpeg.h>
48#elif __has_include(<openjpeg-2.1/openjpeg.h>)
49#include <openjpeg-2.1/openjpeg.h>
50#else
51#error "openjpeg.h not found"
52#endif
53#else
54#include <openjpeg.h>
55#endif
56
57#define J2K_CFMT 0
58#define JP2_CFMT 1
59#define JPT_CFMT 2
60
61static char JP2_HEAD[] = { 0x0, 0x0, 0x0, 0x0C, 0x6A, 0x50, 0x20, 0x20, 0x0D, 0x0A, 0x87, 0x0A };
62static char JP2_MAGIC[] = { 0x0d, 0x0a, 0x87, 0x0a };
63static char J2K_HEAD[] = { 0xFF, 0x4F, 0xFF, 0x51, 0x00 };
64// there seems to be no JPIP/JPT magic string, so we can't load it ...
65
66static void color_sycc_to_rgb(opj_image_t *img);
67
71static void error_callback(const char *msg, void *client_data)
72{
73 FILE *stream = (FILE *)client_data;
74 fprintf(stream, "[j2k_open] Error: %s", msg);
75}
79// static void warning_callback(const char *msg, void *client_data)
80// {
81// FILE *stream = (FILE*)client_data;
82// fprintf(stream, "[j2k_open] Warning: %s", msg);
83// }
87// static void info_callback(const char *msg, void *client_data)
88// {
89// (void)client_data;
90// fprintf(stdout, "[j2k_open] Info: %s", msg);
91// }
92
93static int get_file_format(const char *filename)
94{
95 static const char *extension[] = { "j2k", "jp2", "jpt", "j2c", "jpc" };
96 static const int format[] = { J2K_CFMT, JP2_CFMT, JPT_CFMT, J2K_CFMT, J2K_CFMT };
97 char *ext = strrchr(filename, '.');
98 if(IS_NULL_PTR(ext)) return -1;
99 ext++;
100 if(*ext)
101 {
102 for(unsigned int i = 0; i < sizeof(format) / sizeof(*format); i++)
103 {
104 if(strncasecmp(ext, extension[i], 3) == 0)
105 {
106 return format[i];
107 }
108 }
109 }
110
111 return -1;
112}
113
115{
116 opj_dparameters_t parameters; /* decompression parameters */
117 opj_image_t *image = NULL;
118 FILE *fsrc = NULL;
119 unsigned char src_header[12] = { 0 };
120 opj_codec_t *d_codec = NULL;
121 OPJ_CODEC_FORMAT codec;
122 opj_stream_t *d_stream = NULL; /* Stream */
124
125 /* set decoding parameters to default values */
126 opj_set_default_decoder_parameters(&parameters);
127
128 g_strlcpy(parameters.infile, filename, sizeof(parameters.infile));
129
130 parameters.decod_format = get_file_format(filename);
131 if(parameters.decod_format == -1) return DT_IMAGEIO_FILE_CORRUPTED;
132
133 if(!img->exif_inited) (void)dt_exif_read(img, filename);
134
135 fsrc = g_fopen(filename, "rb");
136 if(IS_NULL_PTR(fsrc))
137 {
138 fprintf(stderr, "[j2k_open] Error: failed to open `%s' for reading\n", filename);
140 }
141 if(fread(src_header, 1, 12, fsrc) != 12)
142 {
143 fclose(fsrc);
144 fprintf(stderr, "[j2k_open] Error: fread returned a number of elements different from the expected.\n");
146 }
147 fclose(fsrc);
148
149 if(memcmp(JP2_HEAD, src_header, sizeof(JP2_HEAD)) == 0 || memcmp(JP2_MAGIC, src_header, sizeof(JP2_MAGIC)) == 0)
150 {
151 parameters.decod_format = JP2_CFMT; // just in case someone used the wrong extension
152 }
153 else if(memcmp(J2K_HEAD, src_header, sizeof(J2K_HEAD)) == 0)
154 {
155 parameters.decod_format = J2K_CFMT; // just in case someone used the wrong extension
156 }
157 else // this will also reject jpt files.
158 {
159 fprintf(stderr, "[j2k_open] Error: `%s' has unsupported file format.\n", filename);
161 }
162
163
164 /* decode the code-stream */
165 /* ---------------------- */
166 if(parameters.decod_format == J2K_CFMT) /* JPEG-2000 codestream */
167 codec = OPJ_CODEC_J2K;
168 else if(parameters.decod_format == JP2_CFMT) /* JPEG 2000 compressed image data */
169 codec = OPJ_CODEC_JP2;
170 else if(parameters.decod_format == JPT_CFMT) /* JPEG 2000, JPIP */
171 codec = OPJ_CODEC_JPT;
172 else
173 {
174 return DT_IMAGEIO_FILE_CORRUPTED; // can't happen
175 }
176
177 d_codec = opj_create_decompress(codec);
178 if(IS_NULL_PTR(d_codec))
179 {
180 fprintf(stderr, "[j2k_open] Error: failed to create the decoder\n");
182 }
183
184 /* catch events using our callbacks and give a local context */
185 opj_set_error_handler(d_codec, error_callback, stderr);
186 // opj_set_warning_handler(d_codec, error_callback, stderr);
187 // opj_set_info_handler(d_codec, error_callback, stderr);
188
189 /* Decode JPEG-2000 with using multiple threads */
190 if(!opj_codec_set_threads(d_codec, darktable.num_openmp_threads))
191 {
192 /* This may not seem like a critical error but failure to initialise the treads
193 is a symptom of major resource exhaustion, bail out as quickly as possible */
194 fprintf(stderr, "[j2k_open] Error: failed to setup the threads for decoder %s\n", parameters.infile);
195 opj_destroy_codec(d_codec);
197 }
198
199 /* setup the decoder decoding parameters using user parameters */
200 if(!opj_setup_decoder(d_codec, &parameters))
201 {
202 fprintf(stderr, "[j2k_open] Error: failed to setup the decoder %s\n", parameters.infile);
203 opj_destroy_codec(d_codec);
205 }
206
207 d_stream = opj_stream_create_default_file_stream(parameters.infile, 1);
208 if(IS_NULL_PTR(d_stream))
209 {
210 fprintf(stderr, "[j2k_open] Error: failed to create the stream from the file %s\n", parameters.infile);
211 opj_destroy_codec(d_codec);
213 }
214
215 /* Read the main header of the codestream and if necessary the JP2 boxes*/
216 if(!opj_read_header(d_stream, d_codec, &image))
217 {
218 fprintf(stderr, "[j2k_open] Error: failed to read the header\n");
219 opj_stream_destroy(d_stream);
220 opj_destroy_codec(d_codec);
221 opj_image_destroy(image);
222 return EXIT_FAILURE;
223 }
224
225 /* Get the decoded image */
226 if(!(opj_decode(d_codec, d_stream, image) && opj_end_decompress(d_codec, d_stream)))
227 {
228 fprintf(stderr, "[j2k_open] Error: failed to decode image!\n");
229 opj_destroy_codec(d_codec);
230 opj_stream_destroy(d_stream);
231 opj_image_destroy(image);
233 }
234
235 /* Close the byte stream */
236 opj_stream_destroy(d_stream);
237
238 if(IS_NULL_PTR(image))
239 {
240 fprintf(stderr, "[j2k_open] Error: failed to decode image `%s'\n", filename);
242 goto end_of_the_world;
243 }
244
245 if(image->color_space == OPJ_CLRSPC_SYCC)
246 {
247 color_sycc_to_rgb(image);
248 }
249
250 if(image->icc_profile_buf)
251 {
252#if defined(HAVE_LIBLCMS1) || defined(HAVE_LIBLCMS2)
253 color_apply_icc_profile(image);
254#endif
255
256 dt_free(image->icc_profile_buf);
257 image->icc_profile_len = 0;
258 }
259
260 /* create output image */
261 /* ------------------- */
262 long signed_offsets[4] = { 0, 0, 0, 0 };
263 int float_divs[4] = { 1, 1, 1, 1 };
264
265 // some sanity checks
266 if(image->numcomps == 0 || image->x1 == 0 || image->y1 == 0)
267 {
268 fprintf(stderr, "[j2k_open] Error: invalid raw image parameters in `%s'\n", filename);
270 goto end_of_the_world;
271 }
272
273 for(int i = 0; i < image->numcomps; i++)
274 {
275 if(image->comps[i].w != image->x1 || image->comps[i].h != image->y1)
276 {
277 fprintf(stderr, "[j2k_open] Error: some component has different size in `%s'\n", filename);
279 goto end_of_the_world;
280 }
281 if(image->comps[i].prec > 16)
282 {
283 fprintf(stderr, "[j2k_open] Error: precision %d is larger than 16 in `%s'\n", image->comps[1].prec,
284 filename);
286 goto end_of_the_world;
287 }
288 }
289
290 img->width = image->x1;
291 img->height = image->y1;
292
293 img->dsc.channels = 4;
294 img->dsc.datatype = TYPE_FLOAT;
295 img->dsc.bpp = 4 * sizeof(float);
296 img->dsc.cst = IOP_CS_RGB; // j2k is always RGB
297 img->dsc.filters = 0u;
298 img->flags &= ~DT_IMAGE_RAW;
299 img->flags &= ~DT_IMAGE_HDR;
300 img->flags &= ~DT_IMAGE_S_RAW;
301 img->flags |= DT_IMAGE_LDR;
302 img->loader = LOADER_J2K;
303
304 if(IS_NULL_PTR(mbuf))
305 {
306 ret = DT_IMAGEIO_OK;
307 goto end_of_the_world;
308 }
309
310 float *buf = (float *)dt_mipmap_cache_alloc(mbuf, img);
311 if(IS_NULL_PTR(buf))
312 {
314 goto end_of_the_world;
315 }
316
317 image->numcomps = MIN(image->numcomps, 4);
318
319 for(int i = 0; i < image->numcomps; i++)
320 {
321 if(image->comps[i].sgnd) signed_offsets[i] = 1 << (image->comps[i].prec - 1);
322
323 float_divs[i] = (1 << image->comps[i].prec) - 1;
324 }
325
326 // numcomps == 1 : grey -> r = grey, g = grey, b = grey
327 // numcomps == 2 : grey, alpha -> r = grey, g = grey, b = grey. put alpha into the mix?
328 // numcomps == 3 : rgb -> rgb
329 // numcomps == 4 : rgb, alpha -> rgb. put alpha into the mix?
330
331 // first try: ignore alpha.
332 if(image->numcomps < 3) // 1, 2 => grayscale
333 {
334 for(size_t i = 0; i < (size_t)img->width * img->height; i++)
335 buf[i * 4 + 0] = buf[i * 4 + 1] = buf[i * 4 + 2] = (float)(image->comps[0].data[i] + signed_offsets[0])
336 / float_divs[0];
337 }
338 else // 3, 4 => rgb
339 {
340 for(size_t i = 0; i < (size_t)img->width * img->height; i++)
341 for(int k = 0; k < 3; k++)
342 buf[i * 4 + k] = (float)(image->comps[k].data[i] + signed_offsets[k]) / float_divs[k];
343 }
344
345 ret = DT_IMAGEIO_OK;
346
347end_of_the_world:
348 /* free remaining structures */
349 opj_destroy_codec(d_codec);
350
351 /* free image data structure */
352 opj_image_destroy(image);
353
354 return ret;
355}
356
357int dt_imageio_j2k_read_profile(const char *filename, uint8_t **out)
358{
359 opj_dparameters_t parameters; /* decompression parameters */
360 opj_image_t *image = NULL;
361 FILE *fsrc = NULL;
362 unsigned char src_header[12] = { 0 };
363 opj_codec_t *d_codec = NULL;
364 OPJ_CODEC_FORMAT codec;
365 opj_stream_t *d_stream = NULL; /* Stream */
366 unsigned int length = 0;
367 *out = NULL;
368
369 /* set decoding parameters to default values */
370 opj_set_default_decoder_parameters(&parameters);
371
372 g_strlcpy(parameters.infile, filename, sizeof(parameters.infile));
373
374 parameters.decod_format = get_file_format(filename);
375 if(parameters.decod_format == -1) return DT_IMAGEIO_FILE_CORRUPTED;
376
377 /* read the input file and put it in memory */
378 /* ---------------------------------------- */
379 fsrc = g_fopen(filename, "rb");
380 if(IS_NULL_PTR(fsrc))
381 {
382 fprintf(stderr, "[j2k_read_profile] Error: failed to open `%s' for reading\n", filename);
383 goto another_end_of_the_world;
384 }
385 if(fread(src_header, 1, 12, fsrc) != 12)
386 {
387 fclose(fsrc);
388 fprintf(stderr,
389 "[j2k_read_profile] Error: fread returned a number of elements different from the expected.\n");
390 goto another_end_of_the_world;
391 }
392 fclose(fsrc);
393
394 if(memcmp(JP2_HEAD, src_header, sizeof(JP2_HEAD)) == 0 || memcmp(JP2_MAGIC, src_header, sizeof(JP2_MAGIC)) == 0)
395 {
396 codec = OPJ_CODEC_JP2;
397 }
398 else if(memcmp(J2K_HEAD, src_header, sizeof(J2K_HEAD)) == 0)
399 {
400 codec = OPJ_CODEC_J2K;
401 }
402 else // this will also reject jpt files.
403 {
404 fprintf(stderr, "[j2k_read_profile] Error: `%s' has unsupported file format.\n", filename);
405 goto another_end_of_the_world;
406 }
407
408 /* decode the code-stream */
409 /* ---------------------- */
410
411 /* get a decoder handle */
412 d_codec = opj_create_decompress(codec);
413 if(IS_NULL_PTR(d_codec))
414 {
415 fprintf(stderr, "[j2k_read_profile] Error: failed to create the decoder\n");
417 }
418
419 /* setup the decoder decoding parameters using user parameters */
420 if(!opj_setup_decoder(d_codec, &parameters))
421 {
422 fprintf(stderr, "[j2k_read_profile] Error: failed to setup the decoder %s\n", parameters.infile);
424 }
425
426 d_stream = opj_stream_create_default_file_stream(parameters.infile, 1);
427 if(IS_NULL_PTR(d_stream))
428 {
429 fprintf(stderr, "[j2k_read_profile] Error: failed to create the stream from the file %s\n", parameters.infile);
431 }
432
433 /* Read the main header of the codestream and if necessary the JP2 boxes*/
434 if(!opj_read_header(d_stream, d_codec, &image))
435 {
436 fprintf(stderr, "[j2k_read_profile] Error: failed to read the header\n");
437 opj_stream_destroy(d_stream);
438 opj_destroy_codec(d_codec);
439 opj_image_destroy(image);
440 return EXIT_FAILURE;
441 }
442
443 /* Get the decoded image */
444 if(!(opj_decode(d_codec, d_stream, image) && opj_end_decompress(d_codec, d_stream)))
445 {
446 fprintf(stderr, "[j2k_read_profile] Error: failed to decode image!\n");
447 opj_destroy_codec(d_codec);
448 opj_stream_destroy(d_stream);
449 opj_image_destroy(image);
451 }
452
453 // FIXME: how to do it without fully-decoding the whole image?
454 // opj_jp2_decode() copies the icc_profile_{buf,len}
455 // from opj_codec_t *d_codec d_codec->color into opj_image_t *image, but
456 // opj_codec_t is private type.
457
458 /* Close the byte stream */
459 opj_stream_destroy(d_stream);
460
461 if(IS_NULL_PTR(image))
462 {
463 fprintf(stderr, "[j2k_read_profile] Error: failed to decode image `%s'\n", filename);
464 goto another_end_of_the_world;
465 }
466
467 if(image->icc_profile_len > 0 && image->icc_profile_buf)
468 {
469 length = image->icc_profile_len;
470 *out = (uint8_t *)g_malloc(image->icc_profile_len);
471 memcpy(*out, image->icc_profile_buf, image->icc_profile_len);
472 }
473
474another_end_of_the_world:
475 /* free remaining structures */
476 opj_destroy_codec(d_codec);
477
478 /* free image data structure */
479 opj_image_destroy(image);
480
481 return length;
482}
483
484
485// stolen from openjpeg
486/*--------------------------------------------------------
487Matrix for sYCC, Amendment 1 to IEC 61966-2-1
488
489Y : 0.299 0.587 0.114 :R
490Cb: -0.1687 -0.3312 0.5 :G
491Cr: 0.5 -0.4187 -0.0812 :B
492
493Inverse:
494
495R: 1 -3.68213e-05 1.40199 :Y
496G: 1.00003 -0.344125 -0.714128 :Cb - 2^(prec - 1)
497B: 0.999823 1.77204 -8.04142e-06 :Cr - 2^(prec - 1)
498
499-----------------------------------------------------------*/
500static void sycc_to_rgb(int offset, int upb, int y, int cb, int cr, int *out_r, int *out_g, int *out_b)
501{
502 int r, g, b;
503
504 cb -= offset;
505 cr -= offset;
506 r = y + (int)(1.402 * (float)cr);
507 if(r < 0)
508 r = 0;
509 else if(r > upb)
510 r = upb;
511 *out_r = r;
512
513 g = y - (int)(0.344 * (float)cb + 0.714 * (float)cr);
514 if(g < 0)
515 g = 0;
516 else if(g > upb)
517 g = upb;
518 *out_g = g;
519
520 b = y + (int)(1.772 * (float)cb);
521 if(b < 0)
522 b = 0;
523 else if(b > upb)
524 b = upb;
525 *out_b = b;
526}
527
528static void sycc444_to_rgb(opj_image_t *img)
529{
530 int *d0, *d1, *d2, *r, *g, *b;
531 const int *y, *cb, *cr;
532 size_t maxw, maxh, max;
533 int i, offset, upb;
534
535 i = img->comps[0].prec;
536 offset = 1 << (i - 1);
537 upb = (1 << i) - 1;
538
539 maxw = img->comps[0].w;
540 maxh = img->comps[0].h;
541 max = maxw * maxh;
542
543 y = img->comps[0].data;
544 cb = img->comps[1].data;
545 cr = img->comps[2].data;
546
547 d0 = r = (int *)calloc(max, sizeof(int));
548 d1 = g = (int *)calloc(max, sizeof(int));
549 d2 = b = (int *)calloc(max, sizeof(int));
550
551 for(i = 0; i < max; ++i)
552 {
553 sycc_to_rgb(offset, upb, *y, *cb, *cr, r, g, b);
554 ++y;
555 ++cb;
556 ++cr;
557 ++r;
558 ++g;
559 ++b;
560 }
561 dt_free(img->comps[0].data);
562 img->comps[0].data = d0;
563 dt_free(img->comps[1].data);
564 img->comps[1].data = d1;
565 dt_free(img->comps[2].data);
566 img->comps[2].data = d2;
567} /* sycc444_to_rgb() */
568
569static void sycc422_to_rgb(opj_image_t *img)
570{
571 int *d0, *d1, *d2, *r, *g, *b;
572 const int *y, *cb, *cr;
573 size_t maxw, maxh, max;
574 int offset, upb;
575 int i, j;
576
577 i = img->comps[0].prec;
578 offset = 1 << (i - 1);
579 upb = (1 << i) - 1;
580
581 maxw = img->comps[0].w;
582 maxh = img->comps[0].h;
583 max = maxw * maxh;
584
585 y = img->comps[0].data;
586 cb = img->comps[1].data;
587 cr = img->comps[2].data;
588
589 d0 = r = (int *)calloc(max, sizeof(int));
590 d1 = g = (int *)calloc(max, sizeof(int));
591 d2 = b = (int *)calloc(max, sizeof(int));
592
593 for(i = 0; i < maxh; ++i)
594 {
595 for(j = 0; j < maxw; j += 2)
596 {
597 sycc_to_rgb(offset, upb, *y, *cb, *cr, r, g, b);
598 ++y;
599 ++r;
600 ++g;
601 ++b;
602
603 sycc_to_rgb(offset, upb, *y, *cb, *cr, r, g, b);
604 ++y;
605 ++r;
606 ++g;
607 ++b;
608 ++cb;
609 ++cr;
610 }
611 }
612 dt_free(img->comps[0].data);
613 img->comps[0].data = d0;
614 dt_free(img->comps[1].data);
615 img->comps[1].data = d1;
616 dt_free(img->comps[2].data);
617 img->comps[2].data = d2;
618
619 img->comps[1].w = maxw;
620 img->comps[1].h = maxh;
621 img->comps[2].w = maxw;
622 img->comps[2].h = maxh;
623 img->comps[1].dx = img->comps[0].dx;
624 img->comps[2].dx = img->comps[0].dx;
625 img->comps[1].dy = img->comps[0].dy;
626 img->comps[2].dy = img->comps[0].dy;
627} /* sycc422_to_rgb() */
628
629static void sycc420_to_rgb(opj_image_t *img)
630{
631 const int offset = 1 << (img->comps[0].prec - 1);
632 const int upb = (1 << img->comps[0].prec) - 1;
633
634 size_t maxw = img->comps[0].w;
635 size_t maxh = img->comps[0].h;
636 size_t max = maxw * maxh;
637
638 const int *y = img->comps[0].data;
639 const int *cb = img->comps[1].data;
640 const int *cr = img->comps[2].data;
641
642 int *d0, *d1, *d2, *r, *g, *b;
643 d0 = r = (int *)calloc(max, sizeof(int));
644 d1 = g = (int *)calloc(max, sizeof(int));
645 d2 = b = (int *)calloc(max, sizeof(int));
646
647 for(int i = 0; i < maxh; i += 2)
648 {
649 const int *ny = y + maxw;
650 int *nr = r + maxw;
651 int *ng = g + maxw;
652 int *nb = b + maxw;
653
654 for(int j = 0; j < maxw; j += 2)
655 {
656 sycc_to_rgb(offset, upb, *y, *cb, *cr, r, g, b);
657 ++y;
658 ++r;
659 ++g;
660 ++b;
661
662 sycc_to_rgb(offset, upb, *y, *cb, *cr, r, g, b);
663 ++y;
664 ++r;
665 ++g;
666 ++b;
667
668 sycc_to_rgb(offset, upb, *ny, *cb, *cr, nr, ng, nb);
669 ++ny;
670 ++nr;
671 ++ng;
672 ++nb;
673
674 sycc_to_rgb(offset, upb, *ny, *cb, *cr, nr, ng, nb);
675 ++ny;
676 ++nr;
677 ++ng;
678 ++nb;
679 ++cb;
680 ++cr;
681 }
682 y += maxw;
683 r += maxw;
684 g += maxw;
685 b += maxw;
686 }
687 dt_free(img->comps[0].data);
688 img->comps[0].data = d0;
689 dt_free(img->comps[1].data);
690 img->comps[1].data = d1;
691 dt_free(img->comps[2].data);
692 img->comps[2].data = d2;
693
694 img->comps[1].w = maxw;
695 img->comps[1].h = maxh;
696 img->comps[2].w = maxw;
697 img->comps[2].h = maxh;
698 img->comps[1].dx = img->comps[0].dx;
699 img->comps[2].dx = img->comps[0].dx;
700 img->comps[1].dy = img->comps[0].dy;
701 img->comps[2].dy = img->comps[0].dy;
702} /* sycc420_to_rgb() */
703
704static void color_sycc_to_rgb(opj_image_t *img)
705{
706 if(img->numcomps < 3)
707 {
708 img->color_space = OPJ_CLRSPC_GRAY;
709 return;
710 }
711
712 if((img->comps[0].dx == 1) && (img->comps[1].dx == 2) && (img->comps[2].dx == 2) && (img->comps[0].dy == 1)
713 && (img->comps[1].dy == 2) && (img->comps[2].dy == 2)) /* horizontal and vertical sub-sample */
714 {
715 sycc420_to_rgb(img);
716 }
717 else if((img->comps[0].dx == 1) && (img->comps[1].dx == 2) && (img->comps[2].dx == 2)
718 && (img->comps[0].dy == 1) && (img->comps[1].dy == 1)
719 && (img->comps[2].dy == 1)) /* horizontal sub-sample only */
720 {
721 sycc422_to_rgb(img);
722 }
723 else if((img->comps[0].dx == 1) && (img->comps[1].dx == 1) && (img->comps[2].dx == 1)
724 && (img->comps[0].dy == 1) && (img->comps[1].dy == 1)
725 && (img->comps[2].dy == 1)) /* no sub-sample */
726 {
727 sycc444_to_rgb(img);
728 }
729 else
730 {
731 fprintf(stderr, "%s:%d:color_sycc_to_rgb\n\tCAN NOT CONVERT\n", __FILE__, __LINE__);
732 return;
733 }
734 img->color_space = OPJ_CLRSPC_SRGB;
735} /* color_sycc_to_rgb() */
736
737// clang-format off
738// modelines: These editor modelines have been set for all relevant files by tools/update_modelines.py
739// vim: shiftwidth=2 expandtab tabstop=2 cindent
740// kate: tab-indents: off; indent-width 2; replace-tabs on; indent-mode cstyle; remove-trailing-spaces modified;
741// clang-format on
const char * extension(dt_imageio_module_data_t *data)
Definition avif.c:645
@ IOP_CS_RGB
const float max
const dt_colormatrix_t dt_aligned_pixel_t out
typedef void((*dt_cache_allocate_t)(void *userdata, dt_cache_entry_t *entry))
darktable_t darktable
Definition darktable.c:181
#define dt_free(ptr)
Definition darktable.h:456
#define IS_NULL_PTR(p)
C is way too permissive with !=, == and if(var) checks, which can mean too many things depending on w...
Definition darktable.h:281
int dt_exif_read(dt_image_t *img, const char *path)
Definition exif.cc:1753
@ TYPE_FLOAT
Definition format.h:46
dt_imageio_retval_t
Definition image.h:78
@ DT_IMAGEIO_OK
Definition image.h:79
@ DT_IMAGEIO_CACHE_FULL
Definition image.h:82
@ DT_IMAGEIO_FILE_CORRUPTED
Definition image.h:81
@ DT_IMAGEIO_FILE_NOT_FOUND
Definition image.h:80
@ DT_IMAGE_LDR
Definition image.h:109
@ LOADER_J2K
Definition image.h:225
static void sycc444_to_rgb(opj_image_t *img)
static void sycc422_to_rgb(opj_image_t *img)
static int get_file_format(const char *filename)
Definition imageio_j2k.c:93
static char JP2_HEAD[]
Definition imageio_j2k.c:61
static void sycc420_to_rgb(opj_image_t *img)
#define J2K_CFMT
Definition imageio_j2k.c:57
static void color_sycc_to_rgb(opj_image_t *img)
int dt_imageio_j2k_read_profile(const char *filename, uint8_t **out)
static char J2K_HEAD[]
Definition imageio_j2k.c:63
static char JP2_MAGIC[]
Definition imageio_j2k.c:62
dt_imageio_retval_t dt_imageio_open_j2k(dt_image_t *img, const char *filename, dt_mipmap_buffer_t *mbuf)
static void sycc_to_rgb(int offset, int upb, int y, int cb, int cr, int *out_r, int *out_g, int *out_b)
static void error_callback(const char *msg, void *client_data)
Definition imageio_j2k.c:71
#define JP2_CFMT
Definition imageio_j2k.c:58
#define JPT_CFMT
Definition imageio_j2k.c:59
float *const restrict const size_t k
void * dt_mipmap_cache_alloc(dt_mipmap_buffer_t *buf, const dt_image_t *img)
const float r
int32_t num_openmp_threads
Definition darktable.h:758
int32_t height
Definition image.h:315
dt_image_loader_t loader
Definition image.h:335
int32_t exif_inited
Definition image.h:283
int32_t flags
Definition image.h:319
int32_t width
Definition image.h:315
dt_iop_buffer_dsc_t dsc
Definition image.h:337
uint32_t filters
Definition format.h:60
unsigned int channels
Definition format.h:54
dt_iop_buffer_type_t datatype
Definition format.h:56
#define MIN(a, b)
Definition thinplate.c:32