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