source: branches/release-1_0/core/dng.c @ 1803

Revision 1803, 26.3 KB checked in by philmoz, 13 months ago (diff)

Fix DNG thumbnail generation bug (thx new123456).
http://chdk.setepontos.com/index.php?topic=7958.msg84122#msg84122

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