Ansel 0.0
A darktable fork - bloat + design vision
Loading...
Searching...
No Matches
imageio_rawspeed.cc
Go to the documentation of this file.
1/*
2 This file is part of darktable,
3 Copyright (C) 2010-2011, 2013-2014 johannes hanika.
4 Copyright (C) 2011 Antony Dovgal.
5 Copyright (C) 2011 Brian Teague.
6 Copyright (C) 2011-2012 Henrik Andersson.
7 Copyright (C) 2011-2014, 2016 Tobias Ellinghaus.
8 Copyright (C) 2012 Jérémy Rosen.
9 Copyright (C) 2012 Richard Wonka.
10 Copyright (C) 2013-2014 Pascal de Bruijn.
11 Copyright (C) 2013-2017, 2019-2021, 2023 Roman Lebedev.
12 Copyright (C) 2013 Simon Spannagel.
13 Copyright (C) 2014 Dan Torop.
14 Copyright (C) 2014-2016 Pedro Côrte-Real.
15 Copyright (C) 2014 Ulrich Pegelow.
16 Copyright (C) 2016-2017 Peter Budai.
17 Copyright (C) 2018 Heiko Bauke.
18 Copyright (C) 2018 Kelvie Wong.
19 Copyright (C) 2019 Aldric Renaudin.
20 Copyright (C) 2019 Andreas Schneider.
21 Copyright (C) 2019 Edgardo Hoszowski.
22 Copyright (C) 2019-2020 Hanno Schwalm.
23 Copyright (C) 2019-2020 Philippe Weyland.
24 Copyright (C) 2020-2022 Pascal Obry.
25 Copyright (C) 2021 Daniel Vogelbacher.
26 Copyright (C) 2022-2026 Aurélien PIERRE.
27 Copyright (C) 2022 Martin Bařinka.
28 Copyright (C) 2022 paolodepetrillo.
29 Copyright (C) 2022 Philipp Lutz.
30 Copyright (C) 2025 Alynx Zhou.
31
32 darktable is free software: you can redistribute it and/or modify
33 it under the terms of the GNU General Public License as published by
34 the Free Software Foundation, either version 3 of the License, or
35 (at your option) any later version.
36
37 darktable is distributed in the hope that it will be useful,
38 but WITHOUT ANY WARRANTY; without even the implied warranty of
39 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
40 GNU General Public License for more details.
41
42 You should have received a copy of the GNU General Public License
43 along with darktable. If not, see <http://www.gnu.org/licenses/>.
44*/
45
46#ifdef _OPENMP
47#include <omp.h>
48#endif
49
50#include "RawSpeed-API.h"
51#include "common/paths.h" // DT_PATH_MAX
52#include "io/FileIOException.h"
53#include "metadata/CameraMetadataException.h"
54#include "parsers/RawParserException.h"
55#include "parsers/FiffParserException.h"
56
57#define TYPE_FLOAT32 RawImageType::F32
58#define TYPE_USHORT16 RawImageType::UINT16
59
60#include <memory>
61#include <mutex>
62
63#define __STDC_LIMIT_MACROS
64
65#include "glib.h"
66
67#include "metadata/exif.h"
72#include "develop/imageop.h"
73#include <stdint.h>
74
75// define this function, it is only declared in rawspeed:
77{
78#ifdef _OPENMP
79 return omp_get_num_procs();
80#else
81 return 1;
82#endif
83}
84
85using namespace rawspeed;
86
88 const RawImage r,
90static CameraMetaData *meta = NULL;
91static std::once_flag meta_once;
92
107{
108 std::call_once(meta_once, [] {
109 char datadir[DT_PATH_MAX] = { 0 }, camfile[DT_PATH_MAX] = { 0 };
110 dt_loc_get_datadir(datadir, sizeof(datadir));
111 dt_concat_path_file(camfile, datadir, "rawspeed/cameras.xml");
112 meta = new CameraMetaData(camfile);
113 });
114}
115
117 const char *model,
118 char *mk,
119 int mk_len,
120 char *md,
121 int md_len,
122 char *al,
123 int al_len)
124{
125 gboolean got_it_done = FALSE;
126 try {
128 // Look for camera in any mode available
129 const Camera *cam = meta->getCamera(maker, model);
130 if(cam)
131 {
132 g_strlcpy(mk, cam->canonical_make.c_str(), mk_len);
133 g_strlcpy(md, cam->canonical_model.c_str(), md_len);
134 g_strlcpy(al, cam->canonical_alias.c_str(), al_len);
135 got_it_done = TRUE;
136 }
137 }
138 catch(const std::exception &exc)
139 {
140 dt_print(DT_DEBUG_ALWAYS, "[rawspeed] %s", exc.what());
141 }
142
143 if(!got_it_done)
144 {
145 // We couldn't find the camera or caught some exception, just punt and pass
146 // through the same values
147 g_strlcpy(mk, maker, mk_len);
148 g_strlcpy(md, model, md_len);
149 g_strlcpy(al, model, al_len);
150 }
151 return got_it_done;
152}
153
154uint32_t dt_rawspeed_crop_dcraw_filters(uint32_t filters, uint32_t crop_x, uint32_t crop_y)
155{
156 if(!filters || filters == 9u) return filters;
157
158 return ColorFilterArray::shiftDcrawFilter(filters, crop_x, crop_y);
159}
160
161// CR3 files are for now handled by LibRAW, we do not want rawspeed to try to open them
162// as this issues lot of error message on the console.
163static gboolean _ignore_image(const gchar *filename)
164{
165 const char *extensions_whitelist[] = { "cr3", NULL };
166 char *ext = g_strrstr(filename, ".");
167 if(IS_NULL_PTR(ext)) return FALSE;
168 ext++;
169 for(const char **i = extensions_whitelist; !IS_NULL_PTR(*i); i++)
170 if(!g_ascii_strncasecmp(ext, *i, strlen(*i)))
171 {
172 return TRUE;
173 }
174 return FALSE;
175}
176
178 const char *filename,
179 dt_mipmap_buffer_t *mbuf)
180{
181 if(_ignore_image(filename))
183
184 if(!img)
185 {
186 dt_print(DT_DEBUG_ALWAYS, "[dt_imageio_open_rawspeed] failed to get dt_image_t for '%s' at %p",
187 filename, mbuf);
189 }
190
191 if(!img->exif_inited)
192 (void)dt_exif_read(img, filename);
193
194 char filen[DT_PATH_MAX] = { 0 };
195 snprintf(filen, sizeof(filen), "%s", filename);
196 FileReader f(filen);
197
198 try
199 {
201
202 // Unserialized on purpose. FileReader::readFile() reads through a local FILE* into a
203 // locally allocated vector and touches no shared mutable state; rawspeed's exception
204 // formatter uses a thread_local buffer (HAVE_CXX_THREAD_LOCAL, set in our generated
205 // rawspeedconfig.h). Verified against the pinned submodule -- see doc/lock-audit.md.
206 auto [storage, storageBuf] = f.readFile();
207
208 RawParser t(storageBuf);
209 std::unique_ptr<RawDecoder> d = t.getDecoder(meta);
210
211 if(!d.get()) return DT_IMAGEIO_UNSUPPORTED_FORMAT;
212
213 d->failOnUnknown = true;
214 d->checkSupport(meta);
215 d->decodeRaw();
216 d->decodeMetaData(meta);
217 RawImage r = d->mRaw;
218
219 const auto errors = r->getErrors();
220 for(const auto &error : errors)
221 dt_print(DT_DEBUG_ALWAYS, "[rawspeed] (%s) %s", img->filename, error.c_str());
222
223 g_strlcpy(img->camera_maker, r->metadata.canonical_make.c_str(), sizeof(img->camera_maker));
224 g_strlcpy(img->camera_model, r->metadata.canonical_model.c_str(), sizeof(img->camera_model));
225 g_strlcpy(img->camera_alias, r->metadata.canonical_alias.c_str(), sizeof(img->camera_alias));
227
228 // We used to partial match the Canon local rebrandings so lets pass on
229 // the value just in those cases to be able to fix old history stacks
230 static const struct {
231 const char *mungedname;
232 const char *origname;
233 } legacy_aliases[] = {
234 {"Canon EOS","Canon EOS REBEL SL1"},
235 {"Canon EOS","Canon EOS Kiss X7"},
236 {"Canon EOS","Canon EOS DIGITAL REBEL XT"},
237 {"Canon EOS","Canon EOS Kiss Digital N"},
238 {"Canon EOS","Canon EOS 350D"},
239 {"Canon EOS","Canon EOS DIGITAL REBEL XSi"},
240 {"Canon EOS","Canon EOS Kiss Digital X2"},
241 {"Canon EOS","Canon EOS Kiss X2"},
242 {"Canon EOS","Canon EOS REBEL T5i"},
243 {"Canon EOS","Canon EOS Kiss X7i"},
244 {"Canon EOS","Canon EOS Rebel T6i"},
245 {"Canon EOS","Canon EOS Kiss X8i"},
246 {"Canon EOS","Canon EOS Rebel T6s"},
247 {"Canon EOS","Canon EOS 8000D"},
248 {"Canon EOS","Canon EOS REBEL T1i"},
249 {"Canon EOS","Canon EOS Kiss X3"},
250 {"Canon EOS","Canon EOS REBEL T2i"},
251 {"Canon EOS","Canon EOS Kiss X4"},
252 {"Canon EOS REBEL T3","Canon EOS REBEL T3i"},
253 {"Canon EOS","Canon EOS Kiss X5"},
254 {"Canon EOS","Canon EOS REBEL T4i"},
255 {"Canon EOS","Canon EOS Kiss X6i"},
256 {"Canon EOS","Canon EOS DIGITAL REBEL XS"},
257 {"Canon EOS","Canon EOS Kiss Digital F"},
258 {"Canon EOS","Canon EOS REBEL T5"},
259 {"Canon EOS","Canon EOS Kiss X70"},
260 {"Canon EOS","Canon EOS DIGITAL REBEL XTi"},
261 {"Canon EOS","Canon EOS Kiss Digital X"},
262 };
263
264 for(uint32_t i = 0; i < (sizeof(legacy_aliases) / sizeof(legacy_aliases[1])); i++)
265 if(!strcmp(legacy_aliases[i].origname, r->metadata.model.c_str()))
266 {
267 g_strlcpy(img->camera_legacy_makermodel, legacy_aliases[i].mungedname, sizeof(img->camera_legacy_makermodel));
268 break;
269 }
270
271 img->raw_black_level = r->blackLevel;
272 img->raw_white_point = r->whitePoint.value_or((1U << 16)-1);
273
274 // NOTE: while it makes sense to always sample black areas when they exist,
275 // black area handling is broken in rawspeed, so don't do that for now.
276 // https://github.com/darktable-org/rawspeed/issues/389
277 if(!r->blackLevelSeparate)
278 {
279 r->calculateBlackAreas();
280 }
281
282 const auto bl = *(r->blackLevelSeparate->getAsArray1DRef());
283 for(uint8_t i = 0; i < 4; i++)
284 img->raw_black_level_separate[i] = bl(i);
285
286 if(r->blackLevel == -1)
287 {
288 float black = 0.0f;
289 for(uint8_t i = 0; i < 4; i++)
290 {
291 black += img->raw_black_level_separate[i];
292 }
293 black /= 4.0f;
294
295 img->raw_black_level = CLAMP(roundf(black), 0, UINT16_MAX);
296 }
297
298 /*
299 * FIXME
300 * if(r->whitePoint == 65536)
301 * ???
302 */
303
304 /* free auto pointers on spot */
305 d.reset();
306 storage.reset();
307
308 // Grab the WB
309 if(r->metadata.wbCoeffs)
310 {
311 for(int i = 0; i < 4; i++)
312 img->wb_coeffs[i] = (*r->metadata.wbCoeffs)[i];
313 }
314 else
315 {
316 for(int i = 0; i < 4; i++)
317 img->wb_coeffs[i] = 0.0;
318 }
319
320 // Grab the Adobe coeffs
321 const int msize = r->metadata.colorMatrix.size();
322 for(int k = 0; k < 4; k++)
323 for(int i = 0; i < 3; i++)
324 {
325 const int idx = k*3 + i;
326 if(idx < msize)
327 img->adobe_XYZ_to_CAM[k][i] = float(r->metadata.colorMatrix[idx]);
328 else
329 img->adobe_XYZ_to_CAM[k][i] = 0.0f;
330 }
331
332 // Get additional exif tags that are not cached in the database
334
335 if(r->getDataType() == TYPE_FLOAT32)
336 {
337 img->flags |= DT_IMAGE_HDR;
338
339 // We assume that float images should already be normalized.
340 // Also consider 1.0f in binary32 (legacy dt HDR files) as white point magic value;
341 // otherwise (e.g. HDRMerge files), let rawprepare normalize as usual.
342 if(r->whitePoint == 0x3F800000) img->raw_white_point = 1;
343 if(img->raw_white_point == 1)
344 for(int k = 0; k < 4; k++) img->dsc.processed_maximum[k] = 1.0f;
345 }
346 else
347 {
348 // Integer raw (the common case, incl. 8/16-bit Linear Raw / sRAW from film scanners): this
349 // is NOT high dynamic range. rawspeed is the only authority on the *source* datatype here,
350 // because an sRAW is always re-stored as a TYPE_FLOAT buffer in RAM (see the sraw loader),
351 // which makes dt_image_buffer_resolve_flags() unable to tell an integer sRAW from a float
352 // one. We must therefore clear any stale DT_IMAGE_HDR (e.g. a corrupted bit persisted in the
353 // DB) explicitly, otherwise rawprepare picks the HDR normalizer (1.0 instead of the white
354 // level) and divides the already-normalized data to near-zero -> black image (issue: VueScan
355 // 8-bit Linear Raw DNGs with WhiteLevel=65535).
356 img->flags &= ~DT_IMAGE_HDR;
357 }
358
359 img->dsc.filters = 0u;
360
361 // dimensions of uncropped image
362 const iPoint2D dimUncropped = r->getUncroppedDim();
363 img->width = dimUncropped.x;
364 img->height = dimUncropped.y;
365
366 // dimensions of cropped image
367 const iPoint2D dimCropped = r->dim;
368
369 // crop - Top,Left corner
370 const iPoint2D cropTL = r->getCropOffset();
371 img->crop_x = cropTL.x;
372 img->crop_y = cropTL.y;
373
374 // crop - Bottom,Right corner
375 const iPoint2D cropBR = dimUncropped - dimCropped - cropTL;
376 img->crop_width = cropBR.x;
377 img->crop_height = cropBR.y;
378 img->p_width = img->width - img->crop_x - img->crop_width;
379 img->p_height = img->height - img->crop_y - img->crop_height;
380
381 img->fuji_rotation_pos = r->metadata.fujiRotationPos;
382 img->pixel_aspect_ratio = (float)r->metadata.pixelAspectRatio;
383
384 if(!r->isCFA)
385 {
387 return ret;
388 }
389
390 if((r->getDataType() != TYPE_USHORT16) && (r->getDataType() != TYPE_FLOAT32))
392
393 if((r->getBpp() != sizeof(uint16_t)) && (r->getBpp() != sizeof(float)))
395
396 if((r->getDataType() == TYPE_USHORT16) && (r->getBpp() != sizeof(uint16_t)))
398
399 if((r->getDataType() == TYPE_FLOAT32) && (r->getBpp() != sizeof(float)))
401
402 const float cpp = r->getCpp();
403 if(cpp != 1) return DT_IMAGEIO_LOAD_FAILED;
404
405 img->dsc.channels = 1;
406
407 switch(r->getBpp())
408 {
409 case sizeof(uint16_t):
410 img->dsc.datatype = TYPE_UINT16;
411 img->dsc.bpp = sizeof(uint16_t);
412 break;
413 case sizeof(float):
414 img->dsc.datatype = TYPE_FLOAT;
415 img->dsc.bpp = sizeof(float);
416 break;
417 default:
419 }
420
421 // as the X-Trans filters comments later on states, these are for
422 // cropped image, so we need to uncrop them.
423 img->dsc.filters = dt_rawspeed_crop_dcraw_filters(r->cfa.getDcrawFilter(), cropTL.x, cropTL.y);
424
426
427 if(img->dsc.filters)
428 {
429 img->flags &= ~DT_IMAGE_LDR;
430 img->flags |= DT_IMAGE_RAW;
431
432 // special handling for x-trans sensors
433 if(img->dsc.filters == 9u)
434 {
435 // get 6x6 CFA offset from top left of cropped image
436 // NOTE: This is different from how things are done with Bayer
437 // sensors. For these, the CFA in cameras.xml is pre-offset
438 // depending on the distance modulo 2 between raw and usable
439 // image data. For X-Trans, the CFA in cameras.xml is
440 // (currently) aligned with the top left of the raw data.
441 for(int i = 0; i < 6; ++i)
442 for(int j = 0; j < 6; ++j)
443 {
444 img->dsc.xtrans[j][i] = (uint8_t)r->cfa.getColorAt(i % 6, j % 6);
445 }
446 }
447 }
448 // if buf is NULL, we quit the fct here
449 if(!mbuf)
450 {
451 img->dsc.cst = IOP_CS_RAW;
452 img->loader = LOADER_RAWSPEED;
453 return DT_IMAGEIO_OK;
454 }
455
456 void *buf = dt_mipmap_cache_alloc(mbuf, img);
457 if(IS_NULL_PTR(buf)) return DT_IMAGEIO_CACHE_FULL;
458
459 /*
460 * since we do not want to crop black borders at this stage,
461 * and we do not want to rotate image, we can just use memcpy,
462 * as it is faster than dt_imageio_flip_buffers, but only if
463 * buffer sizes are equal,
464 * (from Klaus: r->pitch may differ from DT pitch (line to line spacing))
465 * else fallback to generic dt_imageio_flip_buffers()
466 */
467 const size_t bufSize_mipmap = (size_t)img->width * img->height * r->getBpp();
468 const size_t bufSize_rawspeed = (size_t)r->pitch * dimUncropped.y;
469 if(bufSize_mipmap == bufSize_rawspeed)
470 {
471 memcpy(buf, (char *)(&(r->getByteDataAsUncroppedArray2DRef()(0, 0))), bufSize_mipmap);
472 }
473 else
474 {
475 dt_imageio_flip_buffers((char *)buf, (char *)(&(r->getByteDataAsUncroppedArray2DRef()(0, 0))), r->getBpp(),
476 dimUncropped.x, dimUncropped.y, dimUncropped.x, dimUncropped.y, r->pitch,
478 }
479
480 // Check if the camera is missing samples
481 const Camera *cam = meta->getCamera(r->metadata.make.c_str(),
482 r->metadata.model.c_str(),
483 r->metadata.mode.c_str());
484
485 if(cam && cam->supportStatus == Camera::SupportStatus::SupportedNoSamples)
487 }
488 catch(const rawspeed::IOException &exc)
489 {
490 dt_print(DT_DEBUG_ALWAYS, "[rawspeed] (%s) I/O error: %s", img->filename, exc.what());
491 return DT_IMAGEIO_IOERROR;
492 }
493 catch(const rawspeed::FileIOException &exc)
494 {
495 dt_print(DT_DEBUG_ALWAYS, "[rawspeed] (%s) File I/O error: %s", img->filename, exc.what());
496 return DT_IMAGEIO_IOERROR;
497 }
498 catch(const rawspeed::RawDecoderException &exc)
499 {
500 const char *msg = exc.what();
501 // FIXME FIXME
502 // The following is a nasty hack which will break if exception messages change.
503 // The proper way to handle this is to add two new exception types to Rawspeed and
504 // have them throw the appropriate ones on encountering an unsupported camera model
505 // or unsupported feature (e.g. bit depth, compression, aspect ratio mode, ...)
506 if(msg && (strstr(msg, "Camera not supported") || strstr(msg, "not supported, and not allowed to guess")))
507 {
508 dt_print(DT_DEBUG_ALWAYS, "[rawspeed] Unsupported camera model for %s", img->filename);
510 }
511 else if (msg && strstr(msg, "supported"))
512 {
513 dt_print(DT_DEBUG_ALWAYS, "[rawspeed] (%s) %s", img->filename, msg);
515 }
516 else
517 {
518 dt_print(DT_DEBUG_ALWAYS, "[rawspeed] %s corrupt: %s", img->filename, exc.what());
519 // We can end up here if the loader is called on what is actually
520 // a TIFF file, which mistakenly contains the signature of a raw
521 // format in a TIFF container. So it is very important that the
522 // return code from here directs the execution path through the
523 // fallback loader chain.
525 }
526 }
527 catch(const rawspeed::RawParserException &exc)
528 {
529 dt_print(DT_DEBUG_ALWAYS, "[rawspeed] (%s) CIFF/FIFF error: %s", img->filename, exc.what());
531 }
532 catch(const rawspeed::CameraMetadataException &exc)
533 {
534 dt_print(DT_DEBUG_ALWAYS, "[rawspeed] (%s) metadata error: %s", img->filename, exc.what());
536 }
537 catch(const std::exception &exc)
538 {
539 dt_print(DT_DEBUG_ALWAYS, "[rawspeed] (%s) %s", img->filename, exc.what());
540
541 /* if an exception is raised lets not retry or handle the
542 specific ones, consider the file as corrupted */
544 }
545 catch(...)
546 {
547 dt_print(DT_DEBUG_ALWAYS, "[rawspeed] unhandled exception in imageio_rawspeed");
549 }
550
551 img->dsc.cst = IOP_CS_RAW;
552 img->loader = LOADER_RAWSPEED;
553
554 return DT_IMAGEIO_OK;
555}
556
558 const RawImage r,
559 dt_mipmap_buffer_t *mbuf)
560{
561 // sraw aren't real raw, but not ldr either (need white balance and stuff)
562 img->flags &= ~DT_IMAGE_LDR;
563 img->flags &= ~DT_IMAGE_RAW;
564 img->flags |= DT_IMAGE_S_RAW;
565
566 // actually we want to store full floats here:
567 img->dsc.channels = 4;
568 img->dsc.datatype = TYPE_FLOAT;
569 img->dsc.bpp = 4 * sizeof(float);
570
571 if(r->getDataType() != TYPE_USHORT16 && r->getDataType() != TYPE_FLOAT32)
573
574 const uint32_t cpp = r->getCpp();
575 if(cpp != 1 && cpp != 3 && cpp != 4) return DT_IMAGEIO_FILE_CORRUPTED;
576
577 // if buf is NULL, we quit the fct here
578 if(!mbuf)
579 {
580 img->dsc.cst = IOP_CS_RAW;
581 img->loader = LOADER_RAWSPEED;
582 return DT_IMAGEIO_OK;
583 }
584
585 if(cpp == 1) img->flags |= DT_IMAGE_MONOCHROME;
586
587 void *buf = dt_mipmap_cache_alloc(mbuf, img);
588 if(IS_NULL_PTR(buf)) return DT_IMAGEIO_CACHE_FULL;
589
590 const int height = img->height;
591 const int width = img->width;
592
593 if(cpp == 1)
594 {
595 /*
596 * monochrome image (e.g. Leica M9 monochrom),
597 * we need to copy data from only channel to each of 3 channels
598 */
599
600 if(r->getDataType() == TYPE_USHORT16)
601 {
602 // Fetch the rawspeed view in the serial region: it may throw, and an
603 // exception escaping an OpenMP parallel block calls std::terminate.
604 const Array2DRef<uint16_t> in = r->getU16DataAsUncroppedArray2DRef();
605 __OMP_PARALLEL_FOR_CPP__(shared(in) firstprivate(height, width, buf, cpp))
606 for(int j = 0; j < height; j++)
607 {
608 float *out = ((float *)buf) + (size_t)4 * j * width;
609
610 for(int i = 0; i < width; i++, out += 4)
611 {
612 out[0] = out[1] = out[2] = (float)in(j, cpp * i) / (float)UINT16_MAX;
613 out[3] = 0.0f;
614 }
615 }
616
617 }
618 else // r->getDataType() == TYPE_FLOAT32
619 {
620 // Fetch the rawspeed view in the serial region: it may throw, and an
621 // exception escaping an OpenMP parallel block calls std::terminate.
622 const Array2DRef<float> in = r->getF32DataAsUncroppedArray2DRef();
623 __OMP_PARALLEL_FOR_CPP__(shared(in) firstprivate(height, width, buf, cpp))
624 for(int j = 0; j < height; j++)
625 {
626 float *out = ((float *)buf) + (size_t)4 * j * width;
627
628 for(int i = 0; i < width; i++, out += 4)
629 {
630 out[0] = out[1] = out[2] = in(j, cpp * i);
631 out[3] = 0.0f;
632 }
633 }
634
635 }
636 }
637 else // case cpp == 3 or 4
638 {
639 /*
640 * standard 3-ch image
641 * just copy 3 ch to 3 ch
642 */
643
644 if(r->getDataType() == TYPE_USHORT16)
645 {
646 // Fetch the rawspeed view in the serial region: it may throw, and an
647 // exception escaping an OpenMP parallel block calls std::terminate.
648 const Array2DRef<uint16_t> in = r->getU16DataAsUncroppedArray2DRef();
649 __OMP_PARALLEL_FOR_CPP__(shared(in) firstprivate(height, width, buf, cpp))
650 for(int j = 0; j < height; j++)
651 {
652 float *out = ((float *)buf) + (size_t)4 * j * width;
653
654 for(int i = 0; i < width; i++, out += 4)
655 {
656 for(int k = 0; k < 3; k++)
657 out[k] = (float)in(j, cpp * i + k) / (float)UINT16_MAX;
658 out[3] = 0.0f;
659 }
660 }
661
662 }
663 else // r->getDataType() == TYPE_FLOAT32
664 {
665 // Fetch the rawspeed view in the serial region: it may throw, and an
666 // exception escaping an OpenMP parallel block calls std::terminate.
667 const Array2DRef<float> in = r->getF32DataAsUncroppedArray2DRef();
668 __OMP_PARALLEL_FOR_CPP__(shared(in) firstprivate(height, width, buf, cpp))
669 for(int j = 0; j < height; j++)
670 {
671 float *out = ((float *)buf) + (size_t)4 * j * width;
672
673 for(int i = 0; i < width; i++, out += 4)
674 {
675 for(int k = 0; k < 3; k++)
676 out[k] = in(j, cpp * i + k);
677 out[3] = 0.0f;
678 }
679 }
680
681 }
682 }
683
684 img->dsc.cst = IOP_CS_RGB;
685 img->loader = LOADER_RAWSPEED;
686
687 // Check if the camera is missing samples
688 const Camera *cam = meta->getCamera(r->metadata.make.c_str(),
689 r->metadata.model.c_str(),
690 r->metadata.mode.c_str());
691
692 if(cam && cam->supportStatus == Camera::SupportStatus::SupportedNoSamples)
694
695 return DT_IMAGEIO_OK;
696}
697
698// clang-format off
699// modelines: These editor modelines have been set for all relevant files by tools/update_modelines.py
700// vim: shiftwidth=2 expandtab tabstop=2 cindent
701// kate: tab-indents: off; indent-width 2; replace-tabs on; indent-mode cstyle; remove-trailing-spaces modified;
702// clang-format on
static void error(char *msg)
Definition ashift_lsd.c:202
#define TRUE
Definition ashift_lsd.c:162
#define FALSE
Definition ashift_lsd.c:158
typedef void((*dt_cache_allocate_t)(void *userdata, dt_cache_entry_t *entry))
@ IOP_CS_RAW
@ IOP_CS_RGB
const float f
const int t
const dt_colormatrix_t dt_aligned_pixel_t out
void dt_image_refresh_makermodel(dt_image_t *img)
int dt_exif_read(dt_image_t *img, const char *path)
Definition exif.cc:1994
void dt_exif_img_check_additional_tags(dt_image_t *img, const char *filename)
Definition exif.cc:1055
What a photograph says about itself: the EXIF, IPTC and XMP tags a camera and a cataloguer write,...
void dt_loc_get_datadir(char *datadir, size_t bufsize)
@ TYPE_FLOAT
Definition format.h:56
@ TYPE_UINT16
Definition format.h:57
@ ORIENTATION_NONE
Definition image.h:218
dt_imageio_retval_t
Definition image.h:91
@ DT_IMAGEIO_LOAD_FAILED
Definition image.h:99
@ DT_IMAGEIO_OK
Definition image.h:92
@ DT_IMAGEIO_CACHE_FULL
Definition image.h:95
@ DT_IMAGEIO_UNSUPPORTED_FEATURE
Definition image.h:97
@ DT_IMAGEIO_FILE_CORRUPTED
Definition image.h:94
@ DT_IMAGEIO_UNSUPPORTED_FORMAT
Definition image.h:96
@ DT_IMAGEIO_IOERROR
Definition image.h:100
@ DT_IMAGEIO_UNSUPPORTED_CAMERA
Definition image.h:98
@ DT_IMAGE_S_RAW
Definition image.h:147
@ DT_IMAGE_RAW
Definition image.h:124
@ DT_IMAGE_4BAYER
Definition image.h:140
@ DT_IMAGE_MONOCHROME
Definition image.h:142
@ DT_IMAGE_HDR
Definition image.h:126
@ LOADER_RAWSPEED
Definition image.h:291
__DT_CLONE_TARGETS__ void dt_imageio_flip_buffers(char *out, const char *in, const size_t bpp, const int wd, const int ht, const int fwd, const int fht, const int stride, const dt_image_orientation_t orientation)
#define FILTERS_ARE_4BAYER(filters)
static CameraMetaData * meta
static std::once_flag meta_once
#define TYPE_USHORT16
uint32_t dt_rawspeed_crop_dcraw_filters(uint32_t filters, uint32_t crop_x, uint32_t crop_y)
gboolean dt_rawspeed_lookup_makermodel(const char *maker, const char *model, char *mk, int mk_len, char *md, int md_len, char *al, int al_len)
static gboolean _ignore_image(const gchar *filename)
#define TYPE_FLOAT32
int rawspeed_get_number_of_processor_cores()
static dt_imageio_retval_t dt_imageio_open_rawspeed_sraw(dt_image_t *img, const RawImage r, dt_mipmap_buffer_t *buf)
static void dt_rawspeed_load_meta()
dt_imageio_retval_t dt_imageio_open_rawspeed(dt_image_t *img, const char *filename, dt_mipmap_buffer_t *mbuf)
const char * maker
const char * model
@ DT_DEBUG_ALWAYS
Definition logging.h:49
void dt_print(dt_debug_thread_t thread, const char *msg,...) __attribute__((format(printf
Print to stdout when thread is enabled, prefixed with seconds since startup.
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
void * dt_mipmap_cache_alloc(dt_mipmap_buffer_t *buf, const dt_image_t *img)
uint32_t width
Definition mipmap_cache.c:0
uint32_t height
Definition mipmap_cache.c:1
#define __OMP_PARALLEL_FOR_CPP__(...)
Definition openmp.h:102
#define DT_PATH_MAX
Buffer size for a filesystem path anywhere in Ansel.
Definition paths.h:57
void dt_concat_path_file(char destination[4096], const char path[4096], const char *const file)
Append a constant filename to a variable, stack-based, fixed-sized, directory, and add a / in-between...
Definition darktable.c:2674
const float r
float pixel_aspect_ratio
Definition image.h:443
int32_t height
Definition image.h:397
gboolean camera_missing_sample
Definition image.h:384
char camera_model[64]
Definition image.h:380
uint16_t raw_black_level
Definition image.h:437
dt_image_loader_t loader
Definition image.h:417
char camera_maker[64]
Definition image.h:379
uint32_t raw_white_point
Definition image.h:439
int32_t exif_inited
Definition image.h:365
int32_t crop_height
Definition image.h:398
char camera_legacy_makermodel[128]
Definition image.h:383
int32_t flags
Definition image.h:401
int32_t width
Definition image.h:397
int32_t crop_y
Definition image.h:398
char camera_alias[64]
Definition image.h:381
int32_t crop_x
Definition image.h:398
int32_t p_height
Definition image.h:397
dt_iop_buffer_dsc_t dsc
Definition image.h:419
int32_t p_width
Definition image.h:397
float adobe_XYZ_to_CAM[4][3]
Definition image.h:449
int32_t crop_width
Definition image.h:398
char filename[DT_MAX_FILENAME_LEN]
Definition image.h:386
uint16_t raw_black_level_separate[4]
Definition image.h:438
dt_aligned_pixel_t wb_coeffs
Definition image.h:446
uint32_t fuji_rotation_pos
Definition image.h:442
uint32_t filters
Definition format.h:89
unsigned int channels
Definition format.h:83
uint8_t xtrans[6][6]
Definition format.h:99
dt_iop_buffer_type_t datatype
Definition format.h:85
dt_aligned_pixel_t processed_maximum
Definition format.h:114