Ansel 0.0
A darktable fork - bloat + design vision
Loading...
Searching...
No Matches
imageio_dng.h
Go to the documentation of this file.
1/*
2 This file is part of darktable,
3 Copyright (C) 2011 Henrik Andersson.
4 Copyright (C) 2011, 2013, 2016 johannes hanika.
5 Copyright (C) 2011 Karl Mikaelsson.
6 Copyright (C) 2011, 2014-2017 Tobias Ellinghaus.
7 Copyright (C) 2012 Richard Wonka.
8 Copyright (C) 2014, 2016 Roman Lebedev.
9 Copyright (C) 2019 Andreas Schneider.
10 Copyright (C) 2019 Hanno Schwalm.
11 Copyright (C) 2020 Heiko Bauke.
12 Copyright (C) 2020 parafin.
13 Copyright (C) 2020-2022 Pascal Obry.
14 Copyright (C) 2021 Cobert0.
15 Copyright (C) 2021 Hubert Kowalski.
16 Copyright (C) 2021-2022 Miloš Komarčević.
17 Copyright (C) 2021 Ralf Brown.
18 Copyright (C) 2022 Martin Bařinka.
19
20 darktable is free software: you can redistribute it and/or modify
21 it under the terms of the GNU General Public License as published by
22 the Free Software Foundation, either version 3 of the License, or
23 (at your option) any later version.
24
25 darktable is distributed in the hope that it will be useful,
26 but WITHOUT ANY WARRANTY; without even the implied warranty of
27 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
28 GNU General Public License for more details.
29
30 You should have received a copy of the GNU General Public License
31 along with darktable. If not, see <http://www.gnu.org/licenses/>.
32*/
33
34#ifndef DT_IMAGEIO_IMAGEIO_DNG_H
35#define DT_IMAGEIO_IMAGEIO_DNG_H
36
37// writes buffers as digital negative (dng) raw images
38
39#include <glib/gstdio.h>
40#include <inttypes.h>
41#include <math.h>
42#include <stdio.h>
43#include <stdlib.h>
44#include <string.h>
45
46#include "metadata/exif.h"
48#include "system/simd.h"
49
50
51#define II 1
52#define MM 2
53#define BYTE 1
54#define ASCII 2
55#define SHORT 3
56#define LONG 4
57#define RATIONAL 5
58#define SRATIONAL 10
59
60static inline void dt_imageio_dng_write_buf(uint8_t *buf, int adr, int val)
61{
62 buf[adr + 3] = val & 0xff;
63 buf[adr + 2] = (val >> 8) & 0xff;
64 buf[adr + 1] = (val >> 16) & 0xff;
65 buf[adr] = val >> 24;
66}
67
68static inline uint8_t *dt_imageio_dng_make_tag(
69 uint16_t tag, uint16_t type, uint32_t lng, uint32_t fld,
70 uint8_t *b, uint8_t *cnt)
71{
72 dt_imageio_dng_write_buf(b, 0, (tag << 16) | type);
73 dt_imageio_dng_write_buf(b, 4, lng);
74 dt_imageio_dng_write_buf(b, 8, fld);
75 *cnt = *cnt + 1;
76 return b + 12;
77}
78
79static inline void dt_imageio_dng_convert_rational(float f, int32_t *num, int32_t *den)
80{
81 int32_t sign = 1;
82 if(f < 0)
83 {
84 sign = -1;
85 f = -f;
86 }
87 float mult = 1.0f;
88 while(f * mult - (int)(f * mult + 0.00005f) > 0.0001f) mult++;
89 *den = mult;
90 *num = (int)(*den * f);
91 *num *= sign;
92}
93
95 FILE *fp, uint32_t xs, uint32_t ys, float Tv, float Av,
96 float f, float iso, uint32_t filter,
97 const uint8_t xtrans[6][6],
98 const float whitelevel,
99 const dt_aligned_pixel_t wb_coeffs,
100 const float adobe_XYZ_to_CAM[4][3])
101{
102 const uint32_t channels = 1;
103 uint8_t *b /*, *offs1, *offs2*/;
104 // uint32_t exif_offs;
105 uint8_t buf[1024];
106 uint8_t cnt = 0;
107
108 // this matrix is generic for XYZ->sRGB / D65
109 int m[9] = { 3240454, -1537138, -498531, -969266, 1876010, 41556, 55643, -204025, 1057225 };
110 int den = 1000000;
111
112 memset(buf, 0, sizeof(buf));
113 /* TIFF file header. */
114 buf[0] = 0x4d;
115 buf[1] = 0x4d;
116 buf[3] = 42;
117 buf[7] = 10;
118
119 b = buf + 12;
120 b = dt_imageio_dng_make_tag(254, LONG, 1, 0, b, &cnt); /* New subfile type. */
121 b = dt_imageio_dng_make_tag(256, SHORT, 1, (xs << 16), b, &cnt); /* Image width. */
122 b = dt_imageio_dng_make_tag(257, SHORT, 1, (ys << 16), b, &cnt); /* Image length. */
123 // b = dt_imageio_dng_make_tag( 258, SHORT, channels, 506, b, &cnt ); /* Bits per sample. */
124 b = dt_imageio_dng_make_tag(258, SHORT, 1, 32 << 16, b, &cnt); /* Bits per sample. */
125 // bits per sample: 32-bit float
126 // buf[507] = buf[509] = buf[511] = 32;
127 b = dt_imageio_dng_make_tag(259, SHORT, 1, (1 << 16), b, &cnt); /* Compression. */
128 b = dt_imageio_dng_make_tag(262, SHORT, 1, 32803 << 16, b, &cnt);
129 /* cfa */ // 34892, b, &cnt ); // linear raw /* Photo interp. */
130 // b = dt_imageio_dng_make_tag( 271, ASCII, 8, 494, b, &cnt); // maker, needed for dcraw
131 // b = dt_imageio_dng_make_tag( 272, ASCII, 9, 484, b, &cnt); // model
132 // offs2 = b + 8;
133 b = dt_imageio_dng_make_tag(273, LONG, 1, 584, b, &cnt); /* Strip offset. */
134 b = dt_imageio_dng_make_tag(274, SHORT, 1, 1 << 16, b, &cnt); /* Orientation. */
135 b = dt_imageio_dng_make_tag(277, SHORT, 1, channels << 16, b, &cnt); /* Samples per pixel. */
136 b = dt_imageio_dng_make_tag(278, SHORT, 1, (ys << 16), b, &cnt); /* Rows per strip. */
137 b = dt_imageio_dng_make_tag(279, LONG, 1, (ys * xs * channels * 4), b,
138 &cnt); // 32 bits/channel /* Strip byte count. */
139 b = dt_imageio_dng_make_tag(284, SHORT, 1, (1 << 16), b, &cnt); /* Planar configuration. */
140 b = dt_imageio_dng_make_tag(339, SHORT, 1, (3 << 16), b,
141 &cnt); /* SampleFormat = 3 => ieee floating point */
142
143 if(filter == 9u) // xtrans
144 b = dt_imageio_dng_make_tag(33421, SHORT, 2, (6 << 16) | 6, b, &cnt); /* CFAREPEATEDPATTERNDIM */
145 else
146 b = dt_imageio_dng_make_tag(33421, SHORT, 2, (2 << 16) | 2, b, &cnt); /* CFAREPEATEDPATTERNDIM */
147
148 uint32_t cfapattern = 0;
149 switch(filter)
150 {
151 case 0x94949494:
152 cfapattern = (0 << 24) | (1 << 16) | (1 << 8) | 2; // rggb
153 break;
154 case 0x49494949:
155 cfapattern = (1 << 24) | (2 << 16) | (0 << 8) | 1; // gbrg
156 break;
157 case 0x61616161:
158 cfapattern = (1 << 24) | (0 << 16) | (2 << 8) | 1; // grbg
159 break;
160 default: // case 0x16161616:
161 cfapattern = (2 << 24) | (1 << 16) | (1 << 8) | 0; // bggr
162 break;
163 }
164 if(filter == 9u) // xtrans
165 b = dt_imageio_dng_make_tag(33422, BYTE, 36, 400, b, &cnt); /* CFAPATTERN */
166 else // bayer
167 b = dt_imageio_dng_make_tag(33422, BYTE, 4, cfapattern, b, &cnt); /* CFAPATTERN */
168
169 // b = dt_imageio_dng_make_tag( 306, ASCII, 20, 428, b, &cnt ); // DateTime
170 // offs1 = b + 8;// + 3;
171 // b = dt_imageio_dng_make_tag(34665, LONG, 1, 264, b, &cnt); // exif ifd
172 b = dt_imageio_dng_make_tag(50706, BYTE, 4, (1 << 24) | (2 << 16), b, &cnt); // DNG Version/backward version
173 b = dt_imageio_dng_make_tag(50707, BYTE, 4, (1 << 24) | (1 << 16), b, &cnt);
174 union {
175 float f;
176 uint32_t u;
177 } white;
178 white.f = whitelevel;
179 b = dt_imageio_dng_make_tag(50717, LONG, 1, white.u, b, &cnt); // WhiteLevel in float, actually.
180 b = dt_imageio_dng_make_tag(50721, SRATIONAL, 9, 480, b, &cnt); // ColorMatrix1 (XYZ->native cam)
181 b = dt_imageio_dng_make_tag(50728, RATIONAL, 3, 556, b, &cnt); // AsShotNeutral
182 // b = dt_imageio_dng_make_tag(50729, RATIONAL, 2, 512, b, &cnt); // AsShotWhiteXY
183 b = dt_imageio_dng_make_tag(50778, SHORT, 1, 21 << 16, b, &cnt); // CalibrationIlluminant1
184
185 b = dt_imageio_dng_make_tag(0, 0, 0, 0, b, &cnt); /* Next IFD. */
186 buf[11] = cnt - 1; // write number of directory entries of this ifd
187
188 // exif is written later, by exiv2:
189 // printf("offset: %d\n", b - buf); // find out where we're writing data
190 // apparently this doesn't need byteswap:
191 memcpy(buf+400, xtrans, sizeof(uint8_t)*36);
192
193 // ColorMatrix1 try to get camera matrix else m[k] like before
194 if(!isnan(adobe_XYZ_to_CAM[0][0]))
195 {
196 for(int k= 0; k < 3; k++)
197 for(int i= 0; i < 3; i++)
198 m[k*3+i] = roundf(adobe_XYZ_to_CAM[k][i] * ADOBE_COEFF_FACTOR);
199 den = ADOBE_COEFF_FACTOR;
200 }
201
202 for(int k = 0; k < 9; k++)
203 {
204 dt_imageio_dng_write_buf(buf, 480+k*8, m[k]);
205 dt_imageio_dng_write_buf(buf, 484+k*8, den);
206 }
207
208 // TAG AsShotNeutral: for rawspeed Dngdecoder camera white balance
209 den = 1000000;
210 for(int k = 0; k < 3; k++)
211 {
212 const float coeff = roundf(((float)den * wb_coeffs[1]) / wb_coeffs[k]);
213 dt_imageio_dng_write_buf(buf, 556+k*8, (int)coeff);
214 dt_imageio_dng_write_buf(buf, 560+k*8, den);
215 }
216
217 // dt_imageio_dng_write_buf(buf, offs2-buf, 584);
218 const int written = fwrite(buf, 1, 584, fp);
219 if(written != 584) fprintf(stderr, "[dng_write_header] failed to write image header!\n");
220}
221
222static inline void dt_imageio_write_dng(
223 const char *filename, const float *const pixel, const int wd,
224 const int ht, void *exif, const int exif_len, const uint32_t filter,
225 const uint8_t xtrans[6][6],
226 const float whitelevel,
227 const dt_aligned_pixel_t wb_coeffs,
228 const float adobe_XYZ_to_CAM[4][3])
229{
230 FILE *f = g_fopen(filename, "wb");
231 if(f)
232 {
233 dt_imageio_dng_write_tiff_header(f, wd, ht, 1.0f / 100.0f, 1.0f / 4.0f, 50.0f, 100.0f,
234 filter, xtrans, whitelevel, wb_coeffs, adobe_XYZ_to_CAM);
235 const int k = fwrite(pixel, sizeof(float), (size_t)wd * ht, f);
236 if(k != wd * ht) fprintf(stderr, "[dng_write] Error writing image data to %s\n", filename);
237 fclose(f);
238 if(exif) dt_exif_write_blob(exif, exif_len, filename, 0);
239 }
240}
241
242#undef II
243#undef MM
244#undef BYTE
245#undef ASCII
246#undef SHORT
247#undef LONG
248#undef RATIONAL
249#undef SRATIONAL
250
251#endif // DT_IMAGEIO_IMAGEIO_DNG_H
252
253// clang-format off
254// modelines: These editor modelines have been set for all relevant files by tools/update_modelines.py
255// vim: shiftwidth=2 expandtab tabstop=2 cindent
256// kate: tab-indents: off; indent-width 2; replace-tabs on; indent-mode cstyle; remove-trailing-spaces modified;
257// clang-format on
258
#define m
Definition basecurve.c:283
const float f
const float *const const float coeff[3]
int dt_exif_write_blob(uint8_t *blob, uint32_t size, const char *path, const int compressed)
Definition exif.cc:2057
What a photograph says about itself: the EXIF, IPTC and XMP tags a camera and a cataloguer write,...
#define ADOBE_COEFF_FACTOR
static void dt_imageio_dng_convert_rational(float f, int32_t *num, int32_t *den)
Definition imageio_dng.h:79
#define RATIONAL
Definition imageio_dng.h:57
static uint8_t * dt_imageio_dng_make_tag(uint16_t tag, uint16_t type, uint32_t lng, uint32_t fld, uint8_t *b, uint8_t *cnt)
Definition imageio_dng.h:68
static void dt_imageio_write_dng(const char *filename, const float *const pixel, const int wd, const int ht, void *exif, const int exif_len, const uint32_t filter, const uint8_t xtrans[6][6], const float whitelevel, const dt_aligned_pixel_t wb_coeffs, const float adobe_XYZ_to_CAM[4][3])
#define SHORT
Definition imageio_dng.h:55
#define LONG
Definition imageio_dng.h:56
static void dt_imageio_dng_write_tiff_header(FILE *fp, uint32_t xs, uint32_t ys, float Tv, float Av, float f, float iso, uint32_t filter, const uint8_t xtrans[6][6], const float whitelevel, const dt_aligned_pixel_t wb_coeffs, const float adobe_XYZ_to_CAM[4][3])
Definition imageio_dng.h:94
#define BYTE
Definition imageio_dng.h:53
static void dt_imageio_dng_write_buf(uint8_t *buf, int adr, int val)
Definition imageio_dng.h:60
#define SRATIONAL
Definition imageio_dng.h:58
_lib_location_type_t type
Definition location.c:1
float *const restrict const size_t k
DT_ALIGNED_PIXEL float dt_aligned_pixel_t[4]
Definition simd.h:53
static const dt_aligned_pixel_simd_t sign
Definition simd.h:118