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#pragma once
35
36// writes buffers as digital negative (dng) raw images
37
38#include <inttypes.h>
39#include <stdio.h>
40#include <stdlib.h>
41#include <string.h>
42
43#include "common/darktable.h"
44#include "common/exif.h"
45
46
47#define II 1
48#define MM 2
49#define BYTE 1
50#define ASCII 2
51#define SHORT 3
52#define LONG 4
53#define RATIONAL 5
54#define SRATIONAL 10
55
56static inline void dt_imageio_dng_write_buf(uint8_t *buf, int adr, int val)
57{
58 buf[adr + 3] = val & 0xff;
59 buf[adr + 2] = (val >> 8) & 0xff;
60 buf[adr + 1] = (val >> 16) & 0xff;
61 buf[adr] = val >> 24;
62}
63
64static inline uint8_t *dt_imageio_dng_make_tag(
65 uint16_t tag, uint16_t type, uint32_t lng, uint32_t fld,
66 uint8_t *b, uint8_t *cnt)
67{
68 dt_imageio_dng_write_buf(b, 0, (tag << 16) | type);
71 *cnt = *cnt + 1;
72 return b + 12;
73}
74
75static inline void dt_imageio_dng_convert_rational(float f, int32_t *num, int32_t *den)
76{
77 int32_t sign = 1;
78 if(f < 0)
79 {
80 sign = -1;
81 f = -f;
82 }
83 float mult = 1.0f;
84 while(f * mult - (int)(f * mult + 0.00005f) > 0.0001f) mult++;
85 *den = mult;
86 *num = (int)(*den * f);
87 *num *= sign;
88}
89
91 FILE *fp, uint32_t xs, uint32_t ys, float Tv, float Av,
92 float f, float iso, uint32_t filter,
93 const uint8_t xtrans[6][6],
94 const float whitelevel,
95 const dt_aligned_pixel_t wb_coeffs,
96 const float adobe_XYZ_to_CAM[4][3])
97{
98 const uint32_t channels = 1;
99 uint8_t *b /*, *offs1, *offs2*/;
100 // uint32_t exif_offs;
101 uint8_t buf[1024];
102 uint8_t cnt = 0;
103
104 // this matrix is generic for XYZ->sRGB / D65
105 int m[9] = { 3240454, -1537138, -498531, -969266, 1876010, 41556, 55643, -204025, 1057225 };
106 int den = 1000000;
107
108 memset(buf, 0, sizeof(buf));
109 /* TIFF file header. */
110 buf[0] = 0x4d;
111 buf[1] = 0x4d;
112 buf[3] = 42;
113 buf[7] = 10;
114
115 b = buf + 12;
116 b = dt_imageio_dng_make_tag(254, LONG, 1, 0, b, &cnt); /* New subfile type. */
117 b = dt_imageio_dng_make_tag(256, SHORT, 1, (xs << 16), b, &cnt); /* Image width. */
118 b = dt_imageio_dng_make_tag(257, SHORT, 1, (ys << 16), b, &cnt); /* Image length. */
119 // b = dt_imageio_dng_make_tag( 258, SHORT, channels, 506, b, &cnt ); /* Bits per sample. */
120 b = dt_imageio_dng_make_tag(258, SHORT, 1, 32 << 16, b, &cnt); /* Bits per sample. */
121 // bits per sample: 32-bit float
122 // buf[507] = buf[509] = buf[511] = 32;
123 b = dt_imageio_dng_make_tag(259, SHORT, 1, (1 << 16), b, &cnt); /* Compression. */
124 b = dt_imageio_dng_make_tag(262, SHORT, 1, 32803 << 16, b, &cnt);
125 /* cfa */ // 34892, b, &cnt ); // linear raw /* Photo interp. */
126 // b = dt_imageio_dng_make_tag( 271, ASCII, 8, 494, b, &cnt); // maker, needed for dcraw
127 // b = dt_imageio_dng_make_tag( 272, ASCII, 9, 484, b, &cnt); // model
128 // offs2 = b + 8;
129 b = dt_imageio_dng_make_tag(273, LONG, 1, 584, b, &cnt); /* Strip offset. */
130 b = dt_imageio_dng_make_tag(274, SHORT, 1, 1 << 16, b, &cnt); /* Orientation. */
131 b = dt_imageio_dng_make_tag(277, SHORT, 1, channels << 16, b, &cnt); /* Samples per pixel. */
132 b = dt_imageio_dng_make_tag(278, SHORT, 1, (ys << 16), b, &cnt); /* Rows per strip. */
133 b = dt_imageio_dng_make_tag(279, LONG, 1, (ys * xs * channels * 4), b,
134 &cnt); // 32 bits/channel /* Strip byte count. */
135 b = dt_imageio_dng_make_tag(284, SHORT, 1, (1 << 16), b, &cnt); /* Planar configuration. */
136 b = dt_imageio_dng_make_tag(339, SHORT, 1, (3 << 16), b,
137 &cnt); /* SampleFormat = 3 => ieee floating point */
138
139 if(filter == 9u) // xtrans
140 b = dt_imageio_dng_make_tag(33421, SHORT, 2, (6 << 16) | 6, b, &cnt); /* CFAREPEATEDPATTERNDIM */
141 else
142 b = dt_imageio_dng_make_tag(33421, SHORT, 2, (2 << 16) | 2, b, &cnt); /* CFAREPEATEDPATTERNDIM */
143
144 uint32_t cfapattern = 0;
145 switch(filter)
146 {
147 case 0x94949494:
148 cfapattern = (0 << 24) | (1 << 16) | (1 << 8) | 2; // rggb
149 break;
150 case 0x49494949:
151 cfapattern = (1 << 24) | (2 << 16) | (0 << 8) | 1; // gbrg
152 break;
153 case 0x61616161:
154 cfapattern = (1 << 24) | (0 << 16) | (2 << 8) | 1; // grbg
155 break;
156 default: // case 0x16161616:
157 cfapattern = (2 << 24) | (1 << 16) | (1 << 8) | 0; // bggr
158 break;
159 }
160 if(filter == 9u) // xtrans
161 b = dt_imageio_dng_make_tag(33422, BYTE, 36, 400, b, &cnt); /* CFAPATTERN */
162 else // bayer
163 b = dt_imageio_dng_make_tag(33422, BYTE, 4, cfapattern, b, &cnt); /* CFAPATTERN */
164
165 // b = dt_imageio_dng_make_tag( 306, ASCII, 20, 428, b, &cnt ); // DateTime
166 // offs1 = b + 8;// + 3;
167 // b = dt_imageio_dng_make_tag(34665, LONG, 1, 264, b, &cnt); // exif ifd
168 b = dt_imageio_dng_make_tag(50706, BYTE, 4, (1 << 24) | (2 << 16), b, &cnt); // DNG Version/backward version
169 b = dt_imageio_dng_make_tag(50707, BYTE, 4, (1 << 24) | (1 << 16), b, &cnt);
170 union {
171 float f;
172 uint32_t u;
173 } white;
174 white.f = whitelevel;
175 b = dt_imageio_dng_make_tag(50717, LONG, 1, white.u, b, &cnt); // WhiteLevel in float, actually.
176 b = dt_imageio_dng_make_tag(50721, SRATIONAL, 9, 480, b, &cnt); // ColorMatrix1 (XYZ->native cam)
177 b = dt_imageio_dng_make_tag(50728, RATIONAL, 3, 556, b, &cnt); // AsShotNeutral
178 // b = dt_imageio_dng_make_tag(50729, RATIONAL, 2, 512, b, &cnt); // AsShotWhiteXY
179 b = dt_imageio_dng_make_tag(50778, SHORT, 1, 21 << 16, b, &cnt); // CalibrationIlluminant1
180
181 b = dt_imageio_dng_make_tag(0, 0, 0, 0, b, &cnt); /* Next IFD. */
182 buf[11] = cnt - 1; // write number of directory entries of this ifd
183
184 // exif is written later, by exiv2:
185 // printf("offset: %d\n", b - buf); // find out where we're writing data
186 // apparently this doesn't need byteswap:
187 memcpy(buf+400, xtrans, sizeof(uint8_t)*36);
188
189 // ColorMatrix1 try to get camera matrix else m[k] like before
190 if(!isnan(adobe_XYZ_to_CAM[0][0]))
191 {
192 for(int k= 0; k < 3; k++)
193 for(int i= 0; i < 3; i++)
194 m[k*3+i] = roundf(adobe_XYZ_to_CAM[k][i] * ADOBE_COEFF_FACTOR);
195 den = ADOBE_COEFF_FACTOR;
196 }
197
198 for(int k = 0; k < 9; k++)
199 {
200 dt_imageio_dng_write_buf(buf, 480+k*8, m[k]);
201 dt_imageio_dng_write_buf(buf, 484+k*8, den);
202 }
203
204 // TAG AsShotNeutral: for rawspeed Dngdecoder camera white balance
205 den = 1000000;
206 for(int k = 0; k < 3; k++)
207 {
208 const float coeff = roundf(((float)den * wb_coeffs[1]) / wb_coeffs[k]);
209 dt_imageio_dng_write_buf(buf, 556+k*8, (int)coeff);
210 dt_imageio_dng_write_buf(buf, 560+k*8, den);
211 }
212
213 // dt_imageio_dng_write_buf(buf, offs2-buf, 584);
214 const int written = fwrite(buf, 1, 584, fp);
215 if(written != 584) fprintf(stderr, "[dng_write_header] failed to write image header!\n");
216}
217
218static inline void dt_imageio_write_dng(
219 const char *filename, const float *const pixel, const int wd,
220 const int ht, void *exif, const int exif_len, const uint32_t filter,
221 const uint8_t xtrans[6][6],
222 const float whitelevel,
223 const dt_aligned_pixel_t wb_coeffs,
224 const float adobe_XYZ_to_CAM[4][3])
225{
226 FILE *f = g_fopen(filename, "wb");
227 if(f)
228 {
229 dt_imageio_dng_write_tiff_header(f, wd, ht, 1.0f / 100.0f, 1.0f / 4.0f, 50.0f, 100.0f,
230 filter, xtrans, whitelevel, wb_coeffs, adobe_XYZ_to_CAM);
231 const int k = fwrite(pixel, sizeof(float), (size_t)wd * ht, f);
232 if(k != wd * ht) fprintf(stderr, "[dng_write] Error writing image data to %s\n", filename);
233 fclose(f);
234 if(exif) dt_exif_write_blob(exif, exif_len, filename, 0);
235 }
236}
237
238#undef II
239#undef MM
240#undef BYTE
241#undef ASCII
242#undef SHORT
243#undef LONG
244#undef RATIONAL
245#undef SRATIONAL
246
247// clang-format off
248// modelines: These editor modelines have been set for all relevant files by tools/update_modelines.py
249// vim: shiftwidth=2 expandtab tabstop=2 cindent
250// kate: tab-indents: off; indent-width 2; replace-tabs on; indent-mode cstyle; remove-trailing-spaces modified;
251// clang-format on
252
#define m
Definition basecurve.c:277
const float i
Definition colorspaces_inline_conversions.h:669
const dt_aligned_pixel_t f
Definition colorspaces_inline_conversions.h:256
const float b
Definition colorspaces_inline_conversions.h:1326
int type
Definition common/metadata.c:62
static const dt_aligned_pixel_simd_t sign
Definition darktable.h:475
int dt_exif_write_blob(uint8_t *blob, uint32_t size, const char *path, const int compressed)
Definition exif.cc:1809
#define ADOBE_COEFF_FACTOR
Definition imageio.h:57
static void dt_imageio_dng_convert_rational(float f, int32_t *num, int32_t *den)
Definition imageio_dng.h:75
#define RATIONAL
Definition imageio_dng.h:53
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:64
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])
Definition imageio_dng.h:218
#define SHORT
Definition imageio_dng.h:51
#define LONG
Definition imageio_dng.h:52
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:90
#define BYTE
Definition imageio_dng.h:49
static void dt_imageio_dng_write_buf(uint8_t *buf, int adr, int val)
Definition imageio_dng.h:56
#define SRATIONAL
Definition imageio_dng.h:54
static const float *const const float coeff[3]
Definition iop_profile.h:246