source: branches/reyalp-flt/core/dng.c @ 1516

Revision 1516, 28.1 KB checked in by tsv, 17 months ago (diff)

reyalp-flt branch update:

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