~ubuntu-branches/ubuntu/saucy/darktable/saucy

« back to all changes in this revision

Viewing changes to src/common/imageio_dng.h

  • Committer: Bazaar Package Importer
  • Author(s): David Bremner
  • Date: 2011-04-14 23:42:12 UTC
  • Revision ID: james.westby@ubuntu.com-20110414234212-kuffcz5wiu18v6ra
Tags: upstream-0.8
ImportĀ upstreamĀ versionĀ 0.8

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/*
 
2
    This file is part of darktable,
 
3
    copyright (c) 2011 johannes hanika.
 
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
#ifndef DT_DNG_WRITER_H
 
19
#define DT_DNG_WRITER_H
 
20
 
 
21
// writes buffers as digital negative (dng) raw images
 
22
 
 
23
#include <stdlib.h>
 
24
#include <stdio.h>
 
25
#include <inttypes.h>
 
26
#include <string.h>
 
27
#include "common/exif.h"
 
28
 
 
29
 
 
30
#define II       1
 
31
#define MM       2
 
32
#define BYTE     1
 
33
#define ASCII    2
 
34
#define SHORT    3
 
35
#define LONG     4
 
36
#define RATIONAL 5
 
37
#define SRATIONAL 10
 
38
 
 
39
static inline void
 
40
dt_imageio_dng_write_buf(uint8_t *buf, int adr, int val)
 
41
{
 
42
  buf[adr+3] = val & 0xff;
 
43
  buf[adr+2] = (val>>8) & 0xff;
 
44
  buf[adr+1] = (val>>16) & 0xff;
 
45
  buf[adr  ] = val>>24;
 
46
}
 
47
 
 
48
static inline uint8_t *
 
49
dt_imageio_dng_make_tag ( uint16_t tag, uint16_t type, uint32_t lng,
 
50
                          uint32_t fld, uint8_t *b, uint8_t *cnt )
 
51
{
 
52
  dt_imageio_dng_write_buf(b, 0, (tag<<16)| type);
 
53
  dt_imageio_dng_write_buf(b, 4, lng);
 
54
  dt_imageio_dng_write_buf(b, 8, fld);
 
55
  *cnt = *cnt + 1;
 
56
  return b + 12;
 
57
}
 
58
 
 
59
static inline void
 
60
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.0001f) mult++;
 
70
  *den = mult;
 
71
  *num = (int)(*den * f);
 
72
  *num *= sign;
 
73
}
 
74
 
 
75
static inline void
 
76
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)
 
77
{
 
78
  const uint32_t channels = 1;
 
79
  uint8_t *b, *offs1, *offs2;
 
80
  // uint32_t exif_offs;
 
81
  uint8_t  buf[1024];
 
82
  uint8_t  cnt = 0;
 
83
 
 
84
  memset(buf, 0, 1024);
 
85
  /* TIFF file header.  */
 
86
  buf[0] = 0x4d;
 
87
  buf[1] = 0x4d;
 
88
  buf[3] = 42;
 
89
  buf[7] = 10;
 
90
 
 
91
  b = buf + 12;
 
92
  b = dt_imageio_dng_make_tag(  254, LONG, 1, 0, b, &cnt ); /* New subfile type.  */
 
93
  b = dt_imageio_dng_make_tag(  256, SHORT, 1, (xs<<16), b, &cnt ); /* Image width.  */
 
94
  b = dt_imageio_dng_make_tag(  257, SHORT, 1, (ys<<16), b, &cnt ); /* Image length.  */
 
95
  // b = dt_imageio_dng_make_tag(  258, SHORT, channels, 506, b, &cnt ); /* Bits per sample.  */
 
96
  b = dt_imageio_dng_make_tag(  258, SHORT, 1, 32<<16, b, &cnt ); /* Bits per sample.  */
 
97
  // bits per sample: 32-bit float
 
98
  // buf[507] = buf[509] = buf[511] = 32;
 
99
  b = dt_imageio_dng_make_tag(  259, SHORT, 1, (1<<16), b, &cnt ); /* Compression.  */
 
100
  b = dt_imageio_dng_make_tag(  262, SHORT, 1, 32803<<16, b, &cnt);/* cfa */  //34892, b, &cnt ); // linear raw /* Photo interp.  */
 
101
  // b = dt_imageio_dng_make_tag(  271, ASCII, 8, 494, b, &cnt); // maker, needed for dcraw
 
102
  // b = dt_imageio_dng_make_tag(  272, ASCII, 9, 484, b, &cnt); // model
 
103
  offs2 = b + 8;
 
104
  b = dt_imageio_dng_make_tag(  273, LONG, 1, 584, b, &cnt ); /* Strip offset.  */
 
105
  b = dt_imageio_dng_make_tag(  274, SHORT, 1, 1<<16, b, &cnt ); /* Orientation. */
 
106
  b = dt_imageio_dng_make_tag(  277, SHORT, 1, channels<<16, b, &cnt ); /* Samples per pixel.  */
 
107
  b = dt_imageio_dng_make_tag(  278, SHORT, 1, (ys<<16), b, &cnt); /* Rows per strip.  */
 
108
  b = dt_imageio_dng_make_tag(  279, LONG, 1, (ys*xs*channels*4), b, &cnt ); // 32 bits/channel /* Strip byte count.  */
 
109
  b = dt_imageio_dng_make_tag(  284, SHORT, 1, (1<<16), b, &cnt ); /* Planar configuration.  */
 
110
  b = dt_imageio_dng_make_tag(  339, SHORT, 1, (3<<16), b, &cnt ); /* SampleFormat = 3 => ieee floating point */
 
111
 
 
112
  b = dt_imageio_dng_make_tag(33421, SHORT, 2, (2<<16) | 2, b, &cnt ); /* CFAREPEATEDPATTERNDIM */
 
113
 
 
114
  uint32_t cfapattern = 0;
 
115
  switch(filter)
 
116
  {
 
117
    case 0x94949494:
 
118
      cfapattern = (0<<24) | (1<<16) | (1<<8) | 2; // rggb
 
119
      break;
 
120
    case 0x49494949:
 
121
      cfapattern = (1<<24) | (2<<16) | (0<<8) | 1; // gbrg
 
122
      break;
 
123
    case 0x61616161:
 
124
      cfapattern = (1<<24) | (0<<16) | (2<<8) | 1; // grbg
 
125
      break;
 
126
    default: // case 0x16161616:
 
127
      cfapattern = (2<<24) | (1<<16) | (1<<8) | 0; // bggr
 
128
      break;
 
129
  }
 
130
  b = dt_imageio_dng_make_tag(33422, BYTE, 4, cfapattern, b, &cnt ); /* CFAREPEATEDPATTERNDIM */
 
131
 
 
132
  // b = dt_imageio_dng_make_tag(  306, ASCII, 20, 428, b, &cnt ); // DateTime
 
133
  offs1 = b + 8;// + 3;
 
134
  // b = dt_imageio_dng_make_tag(34665, LONG, 1, 264, b, &cnt); // exif ifd
 
135
  b = dt_imageio_dng_make_tag(50706, BYTE, 4, (1<<24) | (2<<16), b, &cnt); // DNG Version/backward version
 
136
  b = dt_imageio_dng_make_tag(50707, BYTE, 4, (1<<24) | (1<<16), b, &cnt);
 
137
  // b = dt_imageio_dng_make_tag(50708, ASCII, 9, 484, b, &cnt); // unique camera model
 
138
  // b = dt_imageio_dng_make_tag(50721, SRATIONAL, 9, 328, b, &cnt); // ColorMatrix1 (XYZ->native cam)
 
139
  // b = dt_imageio_dng_make_tag(50728, RATIONAL, 3, 512, b, &cnt); // AsShotNeutral
 
140
  // b = dt_imageio_dng_make_tag(50729, RATIONAL, 2, 512, b, &cnt); // AsShotWhiteXY
 
141
  b = dt_imageio_dng_make_tag( 0, 0, 0, 0, b, &cnt ); /* Next IFD.  */
 
142
  buf[11] = cnt-1;
 
143
#if 0
 
144
  // exif is written later, by exiv2:
 
145
  // printf("offset: %d\n", b - buf);
 
146
  // set exif IFD offset
 
147
  exif_offs = b - buf;
 
148
  dt_imageio_dng_write_buf(buf, offs1 - buf, b - buf);
 
149
 
 
150
  b += 2;
 
151
  b = dt_imageio_dng_make_tag(33434, RATIONAL, 1, 400, b, &cnt); // exposure time
 
152
  b = dt_imageio_dng_make_tag(33437, RATIONAL, 1, 408, b, &cnt); // FNumber
 
153
  b = dt_imageio_dng_make_tag(34855, SHORT, 1, ((int)iso)<<16, b, &cnt); // iso speed rating
 
154
  b = dt_imageio_dng_make_tag(37386, RATIONAL, 1, 416, b, &cnt); // focal length
 
155
  b = dt_imageio_dng_make_tag( 0, 0, 0, 0, b, &cnt ); /* Next IFD.  */
 
156
  // buf[253] = cnt-buf[11]-1;
 
157
  buf[exif_offs + 1] = cnt-buf[11]-1;
 
158
 
 
159
  // printf("offset: %d\n", b - buf);
 
160
#endif
 
161
 
 
162
  // mostly garbage below, but i'm too lazy to clean it up:
 
163
 
 
164
  int32_t num, den;
 
165
  // ColorMatrix1
 
166
  float m[9] = { 1, 0, 0, 0, 1, 0, 0, 0, 1};
 
167
  // colorspace_get_xyz_to_cam(m);
 
168
  for(int k=0; k<9; k++)
 
169
  {
 
170
    dt_imageio_dng_convert_rational(m[3*(k%3)+k/3], &num, &den);
 
171
    dt_imageio_dng_write_buf(buf, 328+8*k,   num);
 
172
    dt_imageio_dng_write_buf(buf, 328+8*k+4, den);
 
173
  }
 
174
  // for(int k=332;k<400;k+=8) dt_imageio_dng_write_buf(buf, k, 1); // den
 
175
  // dt_imageio_dng_write_buf(buf, 328, 1);// color matrix1: identity
 
176
  // dt_imageio_dng_write_buf(buf, 360, 1);
 
177
  // dt_imageio_dng_write_buf(buf, 392, 1);
 
178
  dt_imageio_dng_convert_rational(Tv, &num, &den);
 
179
  dt_imageio_dng_write_buf(buf, 400, num); // exposure time
 
180
  dt_imageio_dng_write_buf(buf, 404, den);
 
181
  dt_imageio_dng_convert_rational(Av, &num, &den);
 
182
  dt_imageio_dng_write_buf(buf, 408, num); // fnumber
 
183
  dt_imageio_dng_write_buf(buf, 412, den);
 
184
  dt_imageio_dng_convert_rational(f, &num, &den);
 
185
  dt_imageio_dng_write_buf(buf, 416, num); // focal length
 
186
  dt_imageio_dng_write_buf(buf, 420, den);
 
187
  strncpy((char *)buf+428, "2008:07:15 13:37:00\0", 20); // DateTime
 
188
  strncpy((char *)buf+484, "corona-6\0", 9);
 
189
  strncpy((char *)buf+494, "hanatos\0", 8);
 
190
 
 
191
  // AsShotNeutral
 
192
  // dt_imageio_dng_convert_rational(0.333, &num, &den);
 
193
  // for(int k=0;k<3;k++)
 
194
  // {
 
195
  //   dt_imageio_dng_write_buf(buf, 518+8*k,   num);
 
196
  //   dt_imageio_dng_write_buf(buf, 518+8*k+4, den);
 
197
  // }
 
198
  // AsShotWhiteXY
 
199
  dt_imageio_dng_convert_rational(0.3333, &num, &den);
 
200
  dt_imageio_dng_write_buf(buf, 512, num);
 
201
  dt_imageio_dng_write_buf(buf, 516, den);
 
202
  dt_imageio_dng_convert_rational(0.333, &num, &den);
 
203
  dt_imageio_dng_write_buf(buf, 520, num);
 
204
  dt_imageio_dng_write_buf(buf, 524, den);
 
205
 
 
206
  // dt_imageio_dng_write_buf(buf, offs2-buf, 584);
 
207
  int k = 0;
 
208
  k = fwrite ( buf, 1, 584, fp );
 
209
}
 
210
 
 
211
static inline void
 
212
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)
 
213
{
 
214
  FILE* f = fopen(filename, "wb");
 
215
  int k = 0;
 
216
  if(f)
 
217
  {
 
218
    dt_imageio_dng_write_tiff_header(f, wd, ht, 1.0f/100.0f, 1.0f/4.0f, 50.0f, 100.0f, filter);
 
219
    k = fwrite(pixel, sizeof(float), wd*ht, f);
 
220
    fclose(f);
 
221
    if(exif) dt_exif_write_blob(exif,exif_len,filename);
 
222
  }
 
223
}
 
224
 
 
225
#undef II
 
226
#undef MM
 
227
#undef BYTE
 
228
#undef ASCII
 
229
#undef SHORT
 
230
#undef LONG
 
231
#undef RATIONAL
 
232
#undef SRATIONAL
 
233
#endif
 
234