source: trunk/core/dng.c @ 1809

Revision 1809, 32.8 KB checked in by philmoz, 14 months ago (diff)

Re-work of DNG code to better support cameras with and without GPS.

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