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