source: trunk/core/dng.c @ 1497

Revision 1497, 26.3 KB checked in by philmoz, 17 months ago (diff)

Cleanup of DNG code:

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