source: trunk/core/dng.c @ 1808

Revision 1808, 30.2 KB checked in by philmoz, 13 months ago (diff)

Fix DNG bug introduced in revision 1807 (thx new123456)

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