source: branches/reyalp-ptp-live/core/dng.c @ 1813

Revision 1813, 28.1 KB checked in by reyalp, 13 months ago (diff)

updating live view branch with trunk changes up to r1762

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