source: trunk/core/dng.c @ 1799

Revision 1799, 31.2 KB checked in by philmoz, 14 months ago (diff)

Update for DNG 1.3 additions:

  • restored the previous badpixel.bin generation and mapping
  • added an option to enable CHDK map out bad pixels using badpixel.bin (default is off)

See http://chdk.setepontos.com/index.php?topic=7951.0 for discussion on the changes

  • Property svn:eol-style set to native
Line 
1#include "camera.h"
2
3#include "stdlib.h"
4#include "string.h"
5#include "platform.h"
6#include "conf.h"
7#include "console.h"
8#include "dng.h"
9#include "raw.h"
10#include "action_stack.h"
11#include "gui_mbox.h"
12#include "gui_lang.h"
13#include "gps.h"
14
15//thumbnail
16#define DNG_TH_WIDTH 128
17#define DNG_TH_HEIGHT 96
18// higly recommended that DNG_TH_WIDTH*DNG_TH_HEIGHT would be divisible by 512
19
20struct dir_entry{unsigned short tag; unsigned short type; unsigned int count; unsigned int offset;};
21
22#define T_END       0
23#define T_BYTE      1
24#define T_ASCII     2
25#define T_SHORT     3
26#define T_LONG      4
27#define T_RATIONAL  5
28#define T_SBYTE     6
29#define T_UNDEFINED 7
30#define T_SSHORT    8
31#define T_SLONG     9
32#define T_SRATIONAL 10
33#define T_FLOAT     11
34#define T_DOUBLE    12
35#define T_PTR       0x100   // Stored as long/short etc in DNG header, referenced by pointer in IFD (must be pointer to int variable)
36
37unsigned short get_exp_program_for_exif(int exp_program);
38unsigned short get_orientation_for_exif(short orientation);
39unsigned short get_flash_mode_for_exif(short mode, short fired);
40unsigned short get_metering_mode_for_exif(short metering_mode);
41
42const int cam_BaselineNoise[]           = {1,1};
43const int cam_BaselineSharpness[]       = {4,3};
44const int cam_LinearResponseLimit[]     = {1,1};
45const int cam_AnalogBalance[]           = {1,1,1,1,1,1};
46const char cam_name[32];
47const short cam_PreviewBitsPerSample[]  = {8,8,8};
48const char cam_chdk_ver[]               = HDK_VERSION" ver. "BUILD_NUMBER;
49const int cam_Resolution[]              = {180,1};
50int cam_AsShotNeutral[]                 = {1000,1000,1000,1000,1000,1000};
51static char cam_datetime[20]    = "";                   // DateTimeOriginal
52
53struct t_data_for_exif{
54 short iso;
55 int exp_program;
56 int effective_focal_length;
57 short orientation;
58 short flash_mode;
59 short flash_fired;
60 short metering_mode;
61};
62
63static struct t_data_for_exif exif_data;
64
65#define BE(v)   ((v&0x000000FF)<<24)|((v&0x0000FF00)<<8)|((v&0x00FF0000)>>8)|((v&0xFF000000)>>24)   // Convert to big_endian
66
67static unsigned int badpixel_opcode[] =
68{
69    // *** all values must be in big endian order
70
71    BE(4),              // Count = 4
72
73    BE(4),              // FixBadPixelsConstant = 4
74    BE(0x01030000),     // DNG version = 1.3.0.0
75    BE(1),              // Flags = 1
76    BE(8),              // Opcode length = 8 bytes
77    BE(0),              // Constant = 0
78#if   cam_CFAPattern == 0x02010100
79    BE(0),              // BayerPhase = 0 (top left pixel is red)
80#elif cam_CFAPattern == 0x01020001
81    BE(1),              // BayerPhase = 1 (top left pixel is green in a green/red row)
82#elif cam_CFAPattern == 0x01000201
83    BE(2),              // BayerPhase = 2 (top left pixel is green in a green/blue row)
84#elif cam_CFAPattern == 0x00010102
85    BE(3),              // BayerPhase = 3 (top left pixel is blue)
86#endif
87
88    BE(4),              // FixBadPixelsConstant = 4
89    BE(0x01030000),     // DNG version = 1.3.0.0
90    BE(1),              // Flags = 1
91    BE(8),              // Opcode length = 8 bytes
92    BE(1),              // Constant = 1
93#if   cam_CFAPattern == 0x02010100
94    BE(0),              // BayerPhase = 0 (top left pixel is red)
95#elif cam_CFAPattern == 0x01020001
96    BE(1),              // BayerPhase = 1 (top left pixel is green in a green/red row)
97#elif cam_CFAPattern == 0x01000201
98    BE(2),              // BayerPhase = 2 (top left pixel is green in a green/blue row)
99#elif cam_CFAPattern == 0x00010102
100    BE(3),              // BayerPhase = 3 (top left pixel is blue)
101#endif
102
103    BE(4),              // FixBadPixelsConstant = 4
104    BE(0x01030000),     // DNG version = 1.3.0.0
105    BE(1),              // Flags = 1
106    BE(8),              // Opcode length = 8 bytes
107    BE(2),              // Constant = 2
108#if   cam_CFAPattern == 0x02010100
109    BE(0),              // BayerPhase = 0 (top left pixel is red)
110#elif cam_CFAPattern == 0x01020001
111    BE(1),              // BayerPhase = 1 (top left pixel is green in a green/red row)
112#elif cam_CFAPattern == 0x01000201
113    BE(2),              // BayerPhase = 2 (top left pixel is green in a green/blue row)
114#elif cam_CFAPattern == 0x00010102
115    BE(3),              // BayerPhase = 3 (top left pixel is blue)
116#endif
117
118    BE(4),              // FixBadPixelsConstant = 4
119    BE(0x01030000),     // DNG version = 1.3.0.0
120    BE(1),              // Flags = 1
121    BE(8),              // Opcode length = 8 bytes
122    BE(3),              // Constant = 3
123#if   cam_CFAPattern == 0x02010100
124    BE(0),              // BayerPhase = 0 (top left pixel is red)
125#elif cam_CFAPattern == 0x01020001
126    BE(1),              // BayerPhase = 1 (top left pixel is green in a green/red row)
127#elif cam_CFAPattern == 0x01000201
128    BE(2),              // BayerPhase = 2 (top left pixel is green in a green/blue row)
129#elif cam_CFAPattern == 0x00010102
130    BE(3),              // BayerPhase = 3 (top left pixel is blue)
131#endif
132};
133
134// warning: according to TIFF format specification, elements must be sorted by tag value in ascending order!
135
136struct dir_entry IFD0[]={
137 {0xFE,   T_LONG,       1,  1},                                 // NewSubFileType: Preview Image
138 {0x100,  T_LONG,       1,  DNG_TH_WIDTH},                      // ImageWidth
139 {0x101,  T_LONG,       1,  DNG_TH_HEIGHT},                     // ImageLength
140 {0x102,  T_SHORT,      3,  (int)cam_PreviewBitsPerSample},     // BitsPerSample: 8,8,8
141 {0x103,  T_SHORT,      1,  1},                                 // Compression: Uncompressed
142 {0x106,  T_SHORT,      1,  2},                                 //PhotometricInterpretation: RGB
143 {0x10E,  T_ASCII,      1,  0},                                 // ImageDescription
144 {0x10F,  T_ASCII,      sizeof(CAM_MAKE), (int)CAM_MAKE},       // Make
145 {0x110,  T_ASCII,      32, (int)cam_name},                     //Model: Filled at header generation.
146 {0x111,  T_LONG,       1,  0},                                 //StripOffsets: Offset
147 {0x112,  T_SHORT,      1,  1},                                 //Orientation: 1 - 0th row is top, 0th column is left
148 {0x115,  T_SHORT,      1,  3},                                 // SamplesPerPixel: 3
149 {0x116,  T_SHORT,      1,  DNG_TH_HEIGHT},                     //RowsPerStrip
150 {0x117,  T_LONG,       1,  DNG_TH_WIDTH*DNG_TH_HEIGHT*3},      // StripByteCounts = preview size
151 {0x11C,  T_SHORT,      1,  1},                                 // PlanarConfiguration: 1
152 {0x131,  T_ASCII,      sizeof(cam_chdk_ver), (int)cam_chdk_ver},//Software
153 {0x132,  T_ASCII,      20, (int)cam_datetime},                 // DateTime
154 {0x14A,  T_LONG,       1,  0},                                 //SubIFDs offset
155 {0x8298, T_ASCII,      1,  0},                                 // Copyright
156 {0x8769, T_LONG,       1,  0},                                 //EXIF_IFD offset
157 {0x8825, T_LONG,       1,  0},                                 //GPS_IFD offset
158 {0x9216, T_BYTE,       4,  0x00000001},                        // TIFF/EPStandardID: 1.0.0.0
159 {0xC612, T_BYTE,       4,  0x00000301},                        //DNGVersion: 1.3.0.0
160 {0xC614, T_ASCII,      32, (int)cam_name},                     //UniqueCameraModel. Filled at header generation.
161 {0xC621, T_SRATIONAL,  9,  (int)&camera_sensor.color_matrix1},
162 {0xC627, T_RATIONAL,   3,  (int)cam_AnalogBalance},
163 {0xC628, T_RATIONAL,   3,  (int)cam_AsShotNeutral},
164 {0xC62A, T_SRATIONAL,  1,  (int)&camera_sensor.exposure_bias},
165 {0xC62B, T_RATIONAL,   1,  (int)cam_BaselineNoise},
166 {0xC62C, T_RATIONAL,   1,  (int)cam_BaselineSharpness},
167 {0xC62E, T_RATIONAL,   1,  (int)cam_LinearResponseLimit},
168 {0xC630, T_RATIONAL,   4,  (int)&camera_sensor.lens_info},
169 {0xC65A, T_SHORT|T_PTR,1,  (int)&camera_sensor.calibration_illuminant1},
170 {0, T_END}
171};
172
173                                                                                     
174struct dir_entry IFD1[]={
175 {0xFE,   T_LONG,       1,  0},                                 // NewSubFileType: Main Image
176 {0x100,  T_LONG|T_PTR, 1,  (int)&camera_sensor.raw_rowpix},      // ImageWidth
177 {0x101,  T_LONG|T_PTR, 1,  (int)&camera_sensor.raw_rows},        // ImageLength
178 {0x102,  T_SHORT|T_PTR,1,  (int)&camera_sensor.bits_per_pixel},  // BitsPerSample
179 {0x103,  T_SHORT,      1,  1},                                 // Compression: Uncompressed
180 {0x106,  T_SHORT,      1,  0x8023},                            //PhotometricInterpretation: CFA
181 {0x111,  T_LONG,       1,  0},                                 //StripOffsets: Offset
182 {0x115,  T_SHORT,      1,  1},                                 // SamplesPerPixel: 1
183 {0x116,  T_SHORT|T_PTR,1,  (int)&camera_sensor.raw_rows},        //RowsPerStrip
184 {0x117,  T_LONG|T_PTR, 1,  (int)&camera_sensor.raw_size},        // StripByteCounts = CHDK RAW size
185 {0x11A,  T_RATIONAL,   1,  (int)cam_Resolution},               // XResolution
186 {0x11B,  T_RATIONAL,   1,  (int)cam_Resolution},               // YResolution
187 {0x11C,  T_SHORT,      1,  1},                                 // PlanarConfiguration: 1
188 {0x128,  T_SHORT,      1,  2},                                 // ResolutionUnit: inch
189 {0x828D, T_SHORT,      2,  0x00020002},                        // CFARepeatPatternDim: Rows = 2, Cols = 2
190 {0x828E, T_BYTE|T_PTR, 4,  (int)&camera_sensor.cfa_pattern},
191 {0xC61A, T_LONG|T_PTR, 1,  (int)&camera_sensor.black_level},     // BlackLevel
192 {0xC61D, T_LONG|T_PTR, 1,  (int)&camera_sensor.white_level},     // WhiteLevel
193 {0xC61F, T_LONG,       2,  (int)&camera_sensor.crop.origin},
194 {0xC620, T_LONG,       2,  (int)&camera_sensor.crop.size},
195 {0xC68D, T_LONG,       4,  (int)&camera_sensor.dng_active_area},
196 {0xC740, T_UNDEFINED|T_PTR, sizeof(badpixel_opcode),  (int)&badpixel_opcode},
197 {0, T_END}
198};
199
200
201static int cam_shutter[2]       = { 0, 1000000 };       // Shutter speed
202static int cam_aperture[2]      = { 0, 10 };            // Aperture
203static int cam_apex_shutter[2]  = { 0, 96 };            // Shutter speed in APEX units
204static int cam_apex_aperture[2] = { 0, 96 };            // Aperture in APEX units
205static int cam_exp_bias[2]      = { 0, 96 };
206static int cam_max_av[2]        = { 0, 96 };
207static int cam_focal_length[2]  = { 0, 1000 };
208
209struct dir_entry EXIF_IFD[]={
210 {0x829A, T_RATIONAL,   1,  (int)cam_shutter},          // Shutter speed
211 {0x829D, T_RATIONAL,   1,  (int)cam_aperture},         // Aperture
212 {0x8822, T_SHORT,      1,  0},                         // ExposureProgram
213 {0x8827, T_SHORT|T_PTR,1,  (int)&exif_data.iso},       // ISOSpeedRatings
214 {0x9000, T_UNDEFINED,  4,  0x31323230},                // ExifVersion: 2.21
215 {0x9003, T_ASCII,      20, (int)cam_datetime},         // DateTimeOriginal
216 {0x9201, T_SRATIONAL,  1,  (int)cam_apex_shutter},     // ShutterSpeedValue (APEX units)
217 {0x9202, T_RATIONAL,   1,  (int)cam_apex_aperture},    // ApertureValue (APEX units)
218 {0x9204, T_SRATIONAL,  1,  (int)cam_exp_bias},         // ExposureBias
219 {0x9205, T_RATIONAL,   1,  (int)cam_max_av},           // MaxApertureValue
220 {0x9207, T_SHORT,      1,  0},                         // Metering mode
221 {0x9209, T_SHORT,      1,  0},                         // Flash mode
222 {0x920A, T_RATIONAL,   1,  (int)cam_focal_length},     // FocalLength
223 {0xA405, T_SHORT|T_PTR,1,  (int)&exif_data.effective_focal_length},    // FocalLengthIn35mmFilm
224 {0, T_END}
225};
226
227tGPS gps_data;
228
229struct dir_entry GPS_IFD[]={
230  {0x0000, T_BYTE,              4,  0x00000302},                    //GPSVersionID: 2 3 0 0
231  {0x0001, T_ASCII|T_PTR,       2,  (int)gps_data.latitudeRef},     //North or South Latitude "N\0" or "S\0"
232  {0x0002, T_RATIONAL,          3,  (int)gps_data.latitude},        //Latitude
233  {0x0003, T_ASCII|T_PTR,       2,  (int)gps_data.longitudeRef},    //East or West Latitude "E\0" or "W\0"
234  {0x0004, T_RATIONAL,          3,  (int)gps_data.longitude},       //Longitude
235  {0x0005, T_BYTE|T_PTR,        1,  (int)&gps_data.heightRef},      //AltitudeRef
236  {0x0006, T_RATIONAL,          1,  (int)gps_data.height},          //Altitude
237  {0x0007, T_RATIONAL,          3,  (int)gps_data.timeStamp},       //TimeStamp
238  {0x0009, T_ASCII|T_PTR,       2,  (int)gps_data.status},          //Status
239//{0x000A, T_ASCII,             1,  0},                             //MeasureMode
240  {0x0012, T_ASCII,             7,  (int)gps_data.mapDatum},        //MapDatum 7 + 1 pad byte
241  {0x001D, T_ASCII,             11, (int)gps_data.dateStamp},       //DateStamp 11 + 1 pad byte
242  {0, T_END}
243};
244
245
246int get_type_size(int type){
247 switch(type & 0xFF){
248  case T_BYTE:
249  case T_SBYTE:
250  case T_UNDEFINED:
251  case T_ASCII:     return 1;
252  case T_SHORT:
253  case T_SSHORT:    return 2;
254  case T_LONG:
255  case T_SLONG:
256  case T_FLOAT:     return 4;
257  case T_RATIONAL:
258  case T_SRATIONAL:
259  case T_DOUBLE:    return 8;
260  default:          return 0;
261 }
262}
263
264struct {struct dir_entry* entry; int count;} IFD_LIST[]={{IFD0,0}, {IFD1,0}, {EXIF_IFD,0}, {GPS_IFD, 0}};
265
266#define IFDs (sizeof(IFD_LIST)/sizeof(IFD_LIST[0]))
267
268#define TIFF_HDR_SIZE (8)
269
270char* dng_header_buf;
271int dng_header_buf_size;
272int dng_header_buf_offset;
273char *thumbnail_buf;
274
275void add_to_buf(void* var, int size)
276{
277 memcpy(dng_header_buf+dng_header_buf_offset,var,size);
278 dng_header_buf_offset+=size;
279}
280
281void create_dng_header(){
282 int var;
283 int i,j;
284 int extra_offset;
285 int raw_offset;
286
287 // filling EXIF fields
288
289 gps_getData(&gps_data);
290
291 for (j=0;j<IFDs;j++) {
292  for(i=0; IFD_LIST[j].entry[i].type; i++) {
293    switch (IFD_LIST[j].entry[i].tag) {
294     // For camera name string make sure the 'count' in the IFD header is correct for the string
295     case 0x110 :                                                                                       // CameraName
296     case 0xC614: IFD_LIST[j].entry[i].count = strlen((char*)IFD_LIST[j].entry[i].offset) + 1; break;   // UniqueCameraModel
297     case 0x8822: IFD_LIST[j].entry[i].offset=get_exp_program_for_exif(exif_data.exp_program); break;//ExposureProgram
298     case 0x0112: IFD_LIST[j].entry[i].offset=get_orientation_for_exif(exif_data.orientation); break; //Orientation
299     case 0x9209: IFD_LIST[j].entry[i].offset=get_flash_mode_for_exif(exif_data.flash_mode, exif_data.flash_fired); break; //Flash mode
300     case 0x9207: IFD_LIST[j].entry[i].offset=get_metering_mode_for_exif(exif_data.metering_mode); break; // Metering mode
301    }
302  }
303 }
304 
305 // calculating offset of RAW data and count of directories for each IFD
306
307 raw_offset=TIFF_HDR_SIZE;
308
309 for (j=0;j<IFDs;j++) {
310  IFD_LIST[j].count=0;
311  raw_offset+=6; // IFD header+footer
312  for(i=0; IFD_LIST[j].entry[i].type; i++) {
313   int size_ext;
314   IFD_LIST[j].count++;
315   raw_offset+=12; // IFD directory size
316   size_ext=get_type_size(IFD_LIST[j].entry[i].type)*IFD_LIST[j].entry[i].count;
317   if (size_ext>4) raw_offset+=size_ext+(size_ext&1);
318  }
319 }
320
321 // creating buffer for writing data
322 raw_offset=(raw_offset/512+1)*512; // exlusively for CHDK fast file writing
323 dng_header_buf_size=raw_offset;
324 dng_header_buf=umalloc(raw_offset);
325 dng_header_buf_offset=0;
326 if (!dng_header_buf) return;
327
328 // create buffer for thumbnail
329 thumbnail_buf = malloc(DNG_TH_WIDTH*DNG_TH_HEIGHT*3);
330 if (!thumbnail_buf)
331 {
332     ufree(dng_header_buf);
333     dng_header_buf = 0;
334     return;
335 }
336
337 //  writing  offsets for EXIF IFD and RAW data and calculating offset for extra data
338
339 extra_offset=TIFF_HDR_SIZE;
340
341 for (j=0;j<IFDs;j++) {
342  extra_offset+=6+IFD_LIST[j].count*12; // IFD header+footer
343  for(i=0; IFD_LIST[j].entry[i].type; i++) {
344   if (IFD_LIST[j].entry[i].tag==0x8769) IFD_LIST[j].entry[i].offset=TIFF_HDR_SIZE+(IFD_LIST[0].count+IFD_LIST[1].count)*12+6+6;  // EXIF IFD offset
345   if (IFD_LIST[j].entry[i].tag==0x8825) IFD_LIST[j].entry[i].offset=TIFF_HDR_SIZE+(IFD_LIST[0].count+IFD_LIST[1].count+IFD_LIST[2].count)*12+6+6+6;  // GPS IFD offset
346   if (IFD_LIST[j].entry[i].tag==0x14A)  IFD_LIST[j].entry[i].offset=TIFF_HDR_SIZE+IFD_LIST[0].count*12+6; // SubIFDs offset
347   if (IFD_LIST[j].entry[i].tag==0x111)  {
348    if (j==1) IFD_LIST[j].entry[i].offset=raw_offset+DNG_TH_WIDTH*DNG_TH_HEIGHT*3;  //StripOffsets for main image
349    if (j==0) IFD_LIST[j].entry[i].offset=raw_offset;  //StripOffsets for thumbnail
350   }
351  }
352 }
353
354 // TIFF file header
355
356 var=0x4949; // little endian
357 add_to_buf(&var, sizeof(short));
358 var=42; //An arbitrary but carefully chosen number that further identifies the file as a TIFF file.
359 add_to_buf(&var, sizeof(short));
360 var=0x8; // offset of first IFD
361 add_to_buf(&var, sizeof(int));
362
363
364 // writing IFDs
365
366 for (j=0;j<IFDs;j++) {
367  int size_ext;
368  var=IFD_LIST[j].count;
369  add_to_buf(&var, sizeof(short));
370  for(i=0; IFD_LIST[j].entry[i].type; i++) {
371    add_to_buf(&IFD_LIST[j].entry[i].tag, sizeof(short));
372    unsigned short t = IFD_LIST[j].entry[i].type & 0xFF;
373    add_to_buf(&t, sizeof(short));
374    add_to_buf(&IFD_LIST[j].entry[i].count, sizeof(int));
375    size_ext=get_type_size(IFD_LIST[j].entry[i].type)*IFD_LIST[j].entry[i].count;
376    if (size_ext<=4)
377    {
378        if (IFD_LIST[j].entry[i].type & T_PTR)
379        {
380            add_to_buf((void*)IFD_LIST[j].entry[i].offset, sizeof(int));
381        }
382        else
383        {
384            add_to_buf(&IFD_LIST[j].entry[i].offset, sizeof(int));
385        }
386    }
387    else
388    {
389        add_to_buf(&extra_offset, sizeof(int));
390        extra_offset+=size_ext+(size_ext&1);   
391    }
392  }
393 var=0;
394 add_to_buf(&var, sizeof(int));
395 }
396
397
398 // writing extra data
399
400 for (j=0;j<IFDs;j++) {
401  int size_ext;
402  char zero=0;
403  for(i=0; IFD_LIST[j].entry[i].type; i++) {
404   size_ext=get_type_size(IFD_LIST[j].entry[i].type)*IFD_LIST[j].entry[i].count;
405   if (size_ext>4){
406    add_to_buf((void*)IFD_LIST[j].entry[i].offset, size_ext);
407    if (size_ext&1) add_to_buf(&zero, 1);
408   }
409  }
410 }
411
412 // writing zeros to tail of dng header (just for fun)
413 for (i=dng_header_buf_offset; i<dng_header_buf_size; i++) dng_header_buf[i]=0;
414}
415
416void free_dng_header(void)
417{
418    if (dng_header_buf)
419    {
420        ufree(dng_header_buf);
421        dng_header_buf=NULL;
422    }
423    if (thumbnail_buf)
424    {
425        free(thumbnail_buf);
426        thumbnail_buf = 0;
427    }
428}
429
430unsigned short get_exp_program_for_exif(int exp_program){
431 switch(exp_program){
432  case MODE_M: return 1;
433  case MODE_P: return 2;
434  case MODE_AV: return 3;
435  case MODE_TV: return 4;
436  default: return 0;
437 }
438}
439
440unsigned short get_orientation_for_exif(short orientation){
441 switch(orientation){
442  case  90: return 6;  // Right  - Top
443  case 180: return 3;  // Bottom - Right
444  case 270: return 8;  // Left   - Bottom
445  case   0:            // Top    - Left
446  default : return 1;
447 }
448}
449
450unsigned short get_flash_mode_for_exif(short mode, short fired){
451 fired&=1;
452 switch(mode){
453  case 0: return (3<<3)|fired; // auto
454  case 1: return (1<<3)|fired; // on
455  case 2: return (2<<3)|fired; // off
456  default: return fired;
457 };
458}
459
460unsigned short get_metering_mode_for_exif(short metering_mode){
461 switch (metering_mode){
462  case 0: return 5; // Evaluative
463  case 1: return 3; // Spot
464  case 2: return 2; // CenterWeightedAverage
465  default: return 255; // other
466 }
467}
468
469void capture_data_for_exif(void)
470{
471 short short_prop_val;
472 time_t datetime;
473 struct tm *ttm;
474 extern volatile long shutter_open_time; // defined in platform/generic/capt_seq.c
475 int wb[3];
476
477 exif_data.iso=shooting_get_iso_market();
478
479 // Shutter speed tags
480 get_property_case(camera_info.props.tv, &short_prop_val, sizeof(short_prop_val));
481 cam_shutter[0]      = pow_calc( 1000000, 2, 1, -short_prop_val, 96);
482 cam_apex_shutter[0] = short_prop_val;
483
484 // Date & time tag (note - uses shutter speed from 'short_prop_val' code above)
485 if (shutter_open_time) { datetime = shutter_open_time + pow_calc(1, 2, 1, -short_prop_val, 96); shutter_open_time=0;} // shutter closing time
486 else  datetime = time(NULL);
487 ttm = localtime(&datetime);
488 sprintf(cam_datetime, "%04d:%02d:%02d %02d:%02d:%02d", ttm->tm_year+1900, ttm->tm_mon+1, ttm->tm_mday, ttm->tm_hour, ttm->tm_min, ttm->tm_sec);
489
490 get_property_case(camera_info.props.av, &short_prop_val, sizeof(short_prop_val));
491 cam_aperture[0]      = pow_calc( 10, 2, 1, short_prop_val, 192);
492 cam_apex_aperture[0] = short_prop_val;
493
494 get_property_case(camera_info.props.min_av, &short_prop_val, sizeof(short_prop_val));
495 cam_max_av[0] = short_prop_val;
496
497 get_property_case(camera_info.props.ev_correction_2, &short_prop_val, sizeof(short_prop_val));
498 cam_exp_bias[0] = short_prop_val;
499
500 exif_data.exp_program=mode_get() & MODE_SHOOTING_MASK;
501
502 cam_focal_length[0] = get_focal_length(shooting_get_zoom());
503 exif_data.effective_focal_length = get_effective_focal_length(shooting_get_zoom()) / 1000;
504
505 get_property_case(camera_info.props.orientation_sensor, &exif_data.orientation, sizeof(exif_data.orientation));
506 get_parameter_data(camera_info.params.camera_name, &cam_name, sizeof(cam_name));
507 get_property_case(camera_info.props.flash_mode, &exif_data.flash_mode, sizeof(exif_data.flash_mode));
508 get_property_case(camera_info.props.flash_fire, &exif_data.flash_fired, sizeof(exif_data.flash_fired));
509 get_property_case(camera_info.props.metering_mode, &exif_data.metering_mode, sizeof(exif_data.metering_mode));
510
511 get_property_case(camera_info.props.wb_adj, &wb, sizeof(wb)); 
512 cam_AsShotNeutral[1]=wb[1];
513 cam_AsShotNeutral[3]=wb[0];
514 cam_AsShotNeutral[5]=wb[2];
515}
516
517//-------------------------------------------------------------------
518
519void convert_dng_to_chdk_raw(char* fn){
520 #define BUF_SIZE (32768)
521 FILE *dng, *raw;
522 int *buf;
523 int i;
524 struct STD_stat st;
525 struct utimbuf t;
526
527 if (safe_stat(fn, &st) != 0 || st.st_size<=camera_sensor.raw_size)  return;
528 buf=malloc(BUF_SIZE);
529 if (buf){
530  started();
531  dng=fopen(fn,"rb");
532  if (dng){
533   fread(buf, 1, 8, dng);
534   if (buf[0]==0x2A4949 && buf[1]==8) {  // chdk dng header
535    i=strlen(fn)-3;
536    if (strncmp(fn+i,"CR",2)==0) strcpy(fn+i,"WAV"); else strcpy(fn+i,"CRW");
537    raw=fopen(fn,"w+b");
538    if (raw){
539     fseek(dng, st.st_size-camera_sensor.raw_size, SEEK_SET); // SEEK_END is not working?
540     for (i=0; i<camera_sensor.raw_size/BUF_SIZE; i++) {
541      fread(buf, 1, BUF_SIZE, dng);
542      reverse_bytes_order((char*)buf, BUF_SIZE);
543      fwrite(buf, 1, BUF_SIZE, raw);
544     }
545     fread(buf, 1, camera_sensor.raw_size%BUF_SIZE, dng);
546     reverse_bytes_order((char*)buf, camera_sensor.raw_size%BUF_SIZE);
547     fwrite(buf, 1, camera_sensor.raw_size%BUF_SIZE, raw);
548     fclose(raw);
549     t.actime = t.modtime = time(NULL);
550     utime(fn, &t);
551    } // if (raw)
552   } // if chdk dng header
553  fclose(dng);
554  } //if (dng)
555 free(buf);
556 finished();
557 }  //if (buf)
558}
559
560//-------------------------------------------------------------------
561// Functions for creating DNG thumbnail image
562
563static unsigned char gamma[256];
564
565void fill_gamma_buf(void) {
566    int i;
567    if (gamma[255]) return;
568    for (i=0; i<12; i++) gamma[i]=pow_calc_2(255, i, 255, 0.5, 1);
569    for (i=12; i<64; i++) gamma[i]=pow_calc_2(255, i, 255, 0.4, 1);
570    for (i=64; i<=255; i++) gamma[i]=pow_calc_2(255, i, 255, 0.25, 1);
571}
572
573void create_thumbnail() {
574    register int i, j, x, y, yadj, xadj;
575    register char *buf = thumbnail_buf;
576    register int shift = camera_sensor.bits_per_pixel - 8;
577
578    // The sensor bayer patterns are:
579    //  0x02010100  0x01000201  0x01020001
580    //      R G         G B         G R
581    //      G B         R G         B G
582    // for the second pattern yadj shifts the thumbnail row down one line
583    // for the third pattern xadj shifts the thumbnail row accross one pixel
584    // these make the patterns the same
585    yadj = (camera_sensor.cfa_pattern == 0x01000201) ? 1 : 0;
586    xadj = (camera_sensor.cfa_pattern == 0x01020001) ? 1 : 0;
587
588    for (i=0; i<DNG_TH_HEIGHT; i++)
589        for (j=0; j<DNG_TH_WIDTH; j++)
590        {
591            x = ((camera_sensor.jpeg.x + (camera_sensor.jpeg.width  * j) / DNG_TH_WIDTH)  & 0xFFFFFFFE) + xadj;
592            y = ((camera_sensor.jpeg.y + (camera_sensor.jpeg.height * i) / DNG_TH_HEIGHT) & 0xFFFFFFFE) + yadj;
593
594            *buf++ = gamma[get_raw_pixel(x,y)>>shift];           // red pixel
595            *buf++ = gamma[6*(get_raw_pixel(x+1,y)>>shift)/10];  // green pixel
596            *buf++ = gamma[get_raw_pixel(x+1,y+1)>>shift];       // blue pixel
597        }
598}
599
600//-------------------------------------------------------------------
601// Functions for handling DNG bad pixel file creation and bad pixel
602// removal from images.
603
604#define INIT_BADPIXEL_COUNT -1
605#define INIT_BADPIXEL_FILE -2
606
607#define PATH_BADPIXEL_BIN "A/CHDK/badpixel.bin"
608#define PATH_BAD_TMP_BIN "A/CHDK/bad_tmp.bin"
609
610int init_badpixel_bin_flag; // contants above to count/create file, > 0 num bad pixel
611
612int raw_init_badpixel_bin() {
613    int count;
614    unsigned short c[2];
615    FILE*f;
616    if(init_badpixel_bin_flag == INIT_BADPIXEL_FILE) {
617        f=fopen(PATH_BAD_TMP_BIN,"w+b");
618    } else if (init_badpixel_bin_flag == INIT_BADPIXEL_COUNT) {
619        f=NULL;
620    } else {
621        return 0;
622    }
623    count = 0;
624    for (c[0]=camera_sensor.active_area.x1; c[0]<camera_sensor.active_area.x2; c[0]++)
625    {
626        for (c[1]=camera_sensor.active_area.y1; c[1]<camera_sensor.active_area.y2; c[1]++)
627        {
628            if (get_raw_pixel(c[0],c[1]) <= DNG_BADPIXEL_VALUE_LIMIT)
629            {
630                unsigned short l;
631                for (l=0; l<7 && (c[1]+l+1)<camera_sensor.active_area.y2; l++)
632                    if (get_raw_pixel(c[0],c[1]+l+1) > DNG_BADPIXEL_VALUE_LIMIT)
633                        break;
634                c[1] = c[1] | (l << 13);
635                if (f) fwrite(c, 1, 4, f);
636                c[1] = (c[1] & 0x1FFF) + l;
637                count = count + l + 1;
638            }
639        }
640    }
641    if (f) fclose(f);
642    init_badpixel_bin_flag = count;
643    state_shooting_progress = SHOOTING_PROGRESS_PROCESSING;
644    return 1;
645}
646
647short* binary_list=NULL;
648int binary_count=-1;
649
650void load_bad_pixels_list_b(char* filename) {
651    struct STD_stat st;
652    long filesize;
653    void* ptr;
654    FILE *fd;
655
656        if ( filename==0 )
657         { unload_bad_pixels_list_b(); return; }
658
659    binary_count=-1;
660    if (safe_stat(filename,&st)!=0) return;
661    filesize=st.st_size;
662    if (filesize%(2*sizeof(short)) != 0) return;
663        if (filesize == 0) { binary_count = 0; return; }        // Allow empty badpixel.bin file
664    ptr=malloc(filesize);
665    if (!ptr) return;
666    fd=fopen(filename, "rb");
667    if (fd) {
668        fread(ptr,1, filesize,fd);
669        fclose(fd);
670        binary_list=ptr;
671        binary_count=filesize/(2*sizeof(short));
672    }
673    else free(ptr);
674}
675
676void unload_bad_pixels_list_b(void) {
677    if (binary_list) free(binary_list);
678    binary_list=NULL;
679    binary_count=-1;
680}
681
682void patch_bad_pixels_b(void) {
683    int i;
684    short* ptr=binary_list;
685    short y, cnt;
686    for (i=0; i<binary_count; i++, ptr+=2)
687    {
688        y = ptr[1] & 0x1FFF;
689        cnt = (ptr[1] >> 13) & 7;
690        for (; cnt>=0; cnt--, y++)
691            if (get_raw_pixel(ptr[0], y) <= DNG_BADPIXEL_VALUE_LIMIT)
692                patch_bad_pixel(ptr[0], y);
693    }
694}
695
696int badpixel_list_loaded_b(void) {
697        return (binary_count >= 0) ? 1 : 0;
698}
699
700// -----------------------------------------------
701
702enum BadpixelFSM {
703    BADPIX_START,
704    BADPIX_S1,
705    BADPIX_S2
706};
707
708int badpixel_task_stack(long p) {
709    static unsigned int badpix_cnt1;
710
711    switch(p) {
712        case BADPIX_START:
713            action_pop();
714
715            console_clear();
716            console_add_line("Wait please... ");
717            console_add_line("This takes a few seconds,");
718            console_add_line("don't panic!");
719
720            init_badpixel_bin_flag = INIT_BADPIXEL_COUNT;
721
722            shooting_set_tv96_direct(96, SET_LATER);
723            action_push(BADPIX_S1);
724            action_push(AS_SHOOT);
725            action_push_delay(3000);
726            break;
727        case BADPIX_S1:
728            action_pop();
729
730            badpix_cnt1 = init_badpixel_bin_flag;
731            init_badpixel_bin_flag = INIT_BADPIXEL_FILE;
732            shooting_set_tv96_direct(96, SET_LATER);
733
734            action_push(BADPIX_S2);
735            action_push(AS_SHOOT);
736            break;
737        case BADPIX_S2:
738            action_pop();
739
740            console_clear();
741            if (badpix_cnt1 == init_badpixel_bin_flag) {
742                // TODO script asked confirmation first
743                // should sanity check bad pixel count at least,
744                // wrong buffer address could make badpixel bigger than available mem
745                char msg[32];
746                console_add_line("badpixel.bin created.");
747                sprintf(msg, "Bad pixel count: %d", badpix_cnt1);
748                console_add_line(msg);
749                remove(PATH_BADPIXEL_BIN);
750                rename(PATH_BAD_TMP_BIN,PATH_BADPIXEL_BIN);
751            } else {
752                console_add_line("badpixel.bin failed.");
753                console_add_line("Please try again.");
754            }
755            init_badpixel_bin_flag = 0;
756            remove(PATH_BAD_TMP_BIN);
757
758            action_push_delay(3000);
759            break;
760        default:
761            action_stack_standard(p);
762            break;
763    }
764
765    return 1;
766}
767
768
769void create_badpixel_bin() {
770    if (!(mode_get() & MODE_REC)) {
771        gui_mbox_init(LANG_ERROR, LANG_MSG_RECMODE_REQUIRED, MBOX_BTN_OK|MBOX_TEXT_CENTER, NULL);
772        return;
773    }
774
775    gui_set_mode(&altGuiHandler);
776    action_stack_create(&badpixel_task_stack, BADPIX_START);
777}
778
779//-------------------------------------------------------------------
780// Write DNG header, thumbnail and data to file
781
782void write_dng(int fd, char* rawadr, char* altrawadr, unsigned long uncachedbit)
783{
784        create_dng_header();
785
786    if (dng_header_buf)
787    {
788        fill_gamma_buf();
789        if (conf.dng_badpix_removal)
790            patch_bad_pixels_b();
791        create_thumbnail();
792        write(fd, dng_header_buf, dng_header_buf_size);
793        write(fd, thumbnail_buf, DNG_TH_WIDTH*DNG_TH_HEIGHT*3);
794
795        reverse_bytes_order2(rawadr, altrawadr, camera_sensor.raw_size);
796
797        // Write alternate (inactive) buffer that we reversed the bytes into above (if only one buffer then it will be the active buffer instead)
798        write(fd, (char*)(((unsigned long)altrawadr)|uncachedbit), camera_sensor.raw_size);
799
800        if (rawadr == altrawadr)    // If only one RAW buffer then we have to swap the bytes back
801            reverse_bytes_order2(rawadr, altrawadr, camera_sensor.raw_size);
802
803        free_dng_header();
804    }
805}
806
807/*********** BEGIN OF AUXILARY PART **********************/
808
809#include "module_load.h"
810
811struct libdng_sym libdng = {
812                        MAKE_API_VERSION(1,0),          // apiver: increase major if incompatible changes made in module,
813                                                                                // increase minor if compatible changes made(including extending this struct)
814
815                        create_badpixel_bin,
816                        raw_init_badpixel_bin,
817                        capture_data_for_exif,
818                        load_bad_pixels_list_b,
819                        badpixel_list_loaded_b,
820
821                        convert_dng_to_chdk_raw,
822                        write_dng
823                };
824
825
826//-------------------------------------------
827void* MODULE_EXPORT_LIST[] = {
828        /* 0 */ (void*)EXPORTLIST_MAGIC_NUMBER,
829        /* 1 */ (void*)1,
830
831                        &libdng
832                };
833
834//--------------------------------------------
835int _module_loader( unsigned int* chdk_export_list )
836{
837  if ( chdk_export_list[0] != EXPORTLIST_MAGIC_NUMBER )
838     return 1;
839
840  if ( !API_VERSION_MATCH_REQUIREMENT( camera_sensor.api_version, 1, 0 ) )
841         return 1;
842  if ( !API_VERSION_MATCH_REQUIREMENT( camera_info.api_version, 1, 0 ) )
843         return 1;
844
845  return 0;
846}
847
848
849//---------------------------------------------------------
850// PURPOSE: Finalize module operations (close allocs, etc)
851// RETURN VALUE: 0-ok, 1-fail
852//---------------------------------------------------------
853int _module_unloader()
854{
855        unload_bad_pixels_list_b();
856    free_dng_header();
857    return 0;
858}
859
860
861/******************** Module Information structure ******************/
862
863struct ModuleInfo _module_info = {      MODULEINFO_V1_MAGICNUM,
864                                                                        sizeof(struct ModuleInfo),
865
866                                                                        ANY_CHDK_BRANCH, 0,                     // Requirements of CHDK version
867                                                                        PLATFORMID,                                     // Specify platform dependency
868                                                                        MODULEINFO_FLAG_SYSTEM,         // flag
869                                                                        (int32_t)"DNG (dll)",   // Module name
870                                                                        1, 0,                                           // Module version
871                                                                        (int32_t)"Processing of DNG"
872                                                                 };
873
874
875/*************** END OF AUXILARY PART *******************/
Note: See TracBrowser for help on using the repository browser.