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