root/modules/dng.c

/* [<][>][^][v][top][bottom][index][help] */

DEFINITIONS

This source file includes following definitions.
  1. get_type_size
  2. get_ifd
  3. get_tag
  4. add_to_buf
  5. add_val_to_buf
  6. process_ifd_list
  7. process_entries
  8. inc_ifd_count
  9. calc_ifd_count
  10. inc_raw_offset
  11. calc_raw_offset
  12. calc_extra_offset
  13. add_entry_to_buffer
  14. add_ifd_to_buffer
  15. add_entry_extra_data_to_buffer
  16. add_extra_data_to_buffer
  17. create_dng_header
  18. free_dng_header
  19. get_exp_program_for_exif
  20. get_orientation_for_exif
  21. get_flash_mode_for_exif
  22. get_metering_mode_for_exif
  23. pow_calc_2
  24. pow_calc
  25. capture_data_for_exif
  26. convert_dng_to_chdk_raw
  27. load_dng_to_rawbuffer
  28. create_thumbnail
  29. raw_init_badpixel_bin
  30. unload_bad_pixels_list_b
  31. load_bad_pixels_list_b
  32. patch_bad_pixels_b
  33. badpixel_list_loaded_b
  34. action_stack_BADPIX_S3
  35. action_stack_BADPIX_S2
  36. action_stack_BADPIX_S1
  37. action_stack_BADPIX_START
  38. create_badpixel_bin
  39. reverse_bytes_task
  40. write_dng
  41. create_dng_header_for_ptp
  42. free_dng_header_for_ptp
  43. _module_unloader
  44. _module_can_unload

   1 #include "camera_info.h"
   2 #include "modes.h"
   3 #include "debug_led.h"
   4 #include "clock.h"
   5 #include "properties.h"
   6 #include "shooting.h"
   7 #include "conf.h"
   8 #include "console.h"
   9 #include "raw.h"
  10 #include "action_stack.h"
  11 #include "gui.h"
  12 #include "gui_mbox.h"
  13 #include "gui_lang.h"
  14 #include "gps.h"
  15 #include "math.h"
  16 #include "cache.h"
  17 #include "task.h"
  18 #include "cachebit.h"
  19 #include "remotecap.h"
  20 
  21 #include "dng.h"
  22 #include "module_def.h"
  23 
  24 // Set to 1 when module loaded and active
  25 static int running = 0;
  26 
  27 // thumbnail size
  28 #define DNG_TH_WIDTH 128
  29 #define DNG_TH_HEIGHT 96
  30 #define DNG_TH_BYTES (DNG_TH_WIDTH*DNG_TH_HEIGHT*3)
  31 // highly recommended that DNG_TH_WIDTH*DNG_TH_HEIGHT would be divisible by 512
  32 
  33 // new version to support DNG double buffer
  34 void reverse_bytes_order2(char* from, char* to, int count);
  35 
  36 // IFD directory entry
  37 typedef struct
  38 {
  39     unsigned short tag;
  40     unsigned short type;
  41     unsigned int count;
  42     unsigned int offset;
  43 } dir_entry;
  44 
  45 #define T_EOL       0       // End of List
  46 #define T_BYTE      1
  47 #define T_ASCII     2
  48 #define T_SHORT     3
  49 #define T_LONG      4
  50 #define T_RATIONAL  5
  51 #define T_SBYTE     6
  52 #define T_UNDEFINED 7
  53 #define T_SSHORT    8
  54 #define T_SLONG     9
  55 #define T_SRATIONAL 10
  56 #define T_FLOAT     11
  57 #define T_DOUBLE    12
  58 #define T_PTR       0x100   // Stored as long/short etc in DNG header, referenced by pointer in IFD (must be pointer to int variable)
  59 #define T_SKIP      0x200   // Tag value to be skipped (for marking GPS entries if camera does not have GPS)
  60 
  61 unsigned short get_exp_program_for_exif(int exp_program);
  62 unsigned short get_orientation_for_exif(short orientation);
  63 unsigned short get_flash_mode_for_exif(short mode, short fired);
  64 unsigned short get_metering_mode_for_exif(short metering_mode);
  65 
  66 const int cam_BaselineNoise[]           = {1,1};
  67 const int cam_BaselineSharpness[]       = {4,3};
  68 const int cam_LinearResponseLimit[]     = {1,1};
  69 const int cam_AnalogBalance[]           = {1,1,1,1,1,1};
  70 static char cam_name[32]                = "";
  71 static char artist_name[64]             = "";
  72 static char copyright[64]               = "";
  73 const short cam_PreviewBitsPerSample[]  = {8,8,8};
  74 const int cam_Resolution[]              = {180,1};
  75 static int cam_AsShotNeutral[]          = {1000,1000,1000,1000,1000,1000};
  76 static char cam_datetime[20]            = "";                   // DateTimeOriginal
  77 static char cam_subsectime[4]           = "";                   // DateTimeOriginal (milliseconds component)
  78 static int cam_shutter[2]               = { 0, 1000000 };       // Shutter speed
  79 static int cam_aperture[2]              = { 0, 10 };            // Aperture
  80 static int cam_apex_shutter[2]          = { 0, 96 };            // Shutter speed in APEX units
  81 static int cam_apex_aperture[2]         = { 0, 96 };            // Aperture in APEX units
  82 static int cam_exp_bias[2]              = { 0, 96 };
  83 static int cam_max_av[2]                = { 0, 96 };
  84 static int cam_focal_length[2]          = { 0, 1000 };
  85 static int cam_subject_distance[2]      = { 0, 1000 };
  86 
  87 struct t_data_for_exif{
  88     short iso;
  89     int exp_program;
  90     int effective_focal_length;
  91     short orientation;
  92     short flash_mode;
  93     short flash_fired;
  94     short metering_mode;
  95 };
  96 
  97 static struct t_data_for_exif exif_data;
  98 
  99 #define BE(v)   ((v&0x000000FF)<<24)|((v&0x0000FF00)<<8)|((v&0x00FF0000)>>8)|((v&0xFF000000)>>24)   // Convert to big_endian
 100 
 101 #define BADPIX_CFA_INDEX    6   // Index of CFAPattern value in badpixel_opcodes array
 102 
 103 static unsigned int badpixel_opcode[] =
 104 {
 105     // *** all values must be in big endian order
 106 
 107     BE(1),              // Count = 1
 108 
 109     BE(4),              // FixBadPixelsConstant = 4
 110     BE(0x01030000),     // DNG version = 1.3.0.0
 111     BE(1),              // Flags = 1
 112     BE(8),              // Opcode length = 8 bytes
 113     BE(0),              // Constant = 0
 114     BE(0),              // CFAPattern (set in code below)
 115 };
 116 
 117 // warning: according to TIFF format specification, elements must be sorted by tag value in ascending order!
 118 
 119 // Tags of specific entries in ifd0 below.
 120 #define CAMERA_NAME_TAG             0x110
 121 #define THUMB_DATA_TAG              0x111
 122 #define ORIENTATION_TAG             0x112
 123 #define CHDK_VER_TAG                0x131
 124 #define ARTIST_NAME_TAG             0x13B
 125 #define SUBIFDS_TAG                 0x14A
 126 #define COPYRIGHT_TAG               0x8298
 127 #define EXIF_IFD_TAG                0x8769
 128 #define GPS_IFD_TAG                 0x8825
 129 #define DNG_VERSION_TAG             0xC612
 130 #define UNIQUE_CAMERA_MODEL_TAG     0xC614
 131 #define COLOR_MATRIX2_TAG           0xc622
 132 #define CALIBRATION1_TAG            0xc623
 133 #define CALIBRATION2_TAG            0xc624
 134 #define ILLUMINANT2_TAG             0xc65b
 135 #define FORWARD_MATRIX1_TAG         0xc714
 136 #define FORWARD_MATRIX2_TAG         0xc715
 137 
 138 #define CAM_MAKE                    "Canon"
 139 
 140 dir_entry ifd0[]={
 141     {0xFE,   T_LONG,       1,  1},                                 // NewSubFileType: Preview Image
 142     {0x100,  T_LONG,       1,  DNG_TH_WIDTH},                      // ImageWidth
 143     {0x101,  T_LONG,       1,  DNG_TH_HEIGHT},                     // ImageLength
 144     {0x102,  T_SHORT,      3,  (int)cam_PreviewBitsPerSample},     // BitsPerSample: 8,8,8
 145     {0x103,  T_SHORT,      1,  1},                                 // Compression: Uncompressed
 146     {0x106,  T_SHORT,      1,  2},                                 // PhotometricInterpretation: RGB
 147     {0x10E,  T_ASCII,      1,  0},                                 // ImageDescription
 148     {0x10F,  T_ASCII,      sizeof(CAM_MAKE), (int)CAM_MAKE},       // Make
 149     {0x110,  T_ASCII,      32, (int)cam_name},                     // Model: Filled at header generation.
 150     {0x111,  T_LONG,       1,  0},                                 // StripOffsets: Offset
 151     {0x112,  T_SHORT,      1,  1},                                 // Orientation: 1 - 0th row is top, 0th column is left
 152     {0x115,  T_SHORT,      1,  3},                                 // SamplesPerPixel: 3
 153     {0x116,  T_SHORT,      1,  DNG_TH_HEIGHT},                     // RowsPerStrip
 154     {0x117,  T_LONG,       1,  DNG_TH_BYTES},                      // StripByteCounts = preview size
 155     {0x11C,  T_SHORT,      1,  1},                                 // PlanarConfiguration: 1
 156     {0x131,  T_ASCII|T_PTR,32, 0},                                 // Software
 157     {0x132,  T_ASCII,      20, (int)cam_datetime},                 // DateTime
 158     {0x13B,  T_ASCII|T_PTR,64, (int)artist_name},                  // Artist: Filled at header generation.
 159     {0x14A,  T_LONG,       1,  0},                                 // SubIFDs offset
 160     {0x8298, T_ASCII|T_PTR,64, (int)copyright},                    // Copyright
 161     {0x8769, T_LONG,       1,  0},                                 // EXIF_IFD offset
 162     {0x8825, T_LONG,       1,  0},                                 // GPS_IFD offset
 163     {0x9216, T_BYTE,       4,  0x00000001},                        // TIFF/EPStandardID: 1.0.0.0
 164     {0xC612, T_BYTE,       4,  0x00000301},                        // DNGVersion: 1.3.0.0
 165     {0xC613, T_BYTE,       4,  0x00000101},                        // DNGBackwardVersion: 1.1.0.0
 166     {0xC614, T_ASCII,      32, (int)cam_name},                     // UniqueCameraModel. Filled at header generation.
 167     {0xC621, T_SRATIONAL,  9,  (int)&camera_sensor.color_matrix1},
 168     {0xC622, T_SRATIONAL,  9,  (int)&camera_sensor.color_matrix2},
 169     {0xC623, T_SRATIONAL,  9,  (int)&camera_sensor.camera_calibration1},
 170     {0xC624, T_SRATIONAL,  9,  (int)&camera_sensor.camera_calibration2},
 171     {0xC627, T_RATIONAL,   3,  (int)cam_AnalogBalance},
 172     {0xC628, T_RATIONAL,   3,  (int)cam_AsShotNeutral},
 173     {0xC62A, T_SRATIONAL,  1,  (int)&camera_sensor.exposure_bias},
 174     {0xC62B, T_RATIONAL,   1,  (int)cam_BaselineNoise},
 175     {0xC62C, T_RATIONAL,   1,  (int)cam_BaselineSharpness},
 176     {0xC62E, T_RATIONAL,   1,  (int)cam_LinearResponseLimit},
 177     {0xC630, T_RATIONAL,   4,  (int)&camera_sensor.lens_info},
 178     {0xC65A, T_SHORT|T_PTR,1,  (int)&camera_sensor.calibration_illuminant1}, 
 179     {0xC65B, T_SHORT|T_PTR,1,  (int)&camera_sensor.calibration_illuminant2}, 
 180     {0xC714, T_SRATIONAL,  9,  (int)&camera_sensor.forward_matrix1},
 181     {0xC715, T_SRATIONAL,  9,  (int)&camera_sensor.forward_matrix2},
 182     {0, T_EOL, 0, 0},
 183 };
 184 
 185 // Tags of specific entries in ifd1 below.
 186 #define RAW_DATA_TAG                0x111
 187 #define BADPIXEL_OPCODE_TAG         0xC740
 188 
 189 // Values are calculated based on user selected 'crop size'
 190 static int crop_origin[2];
 191 static int crop_size[2];
 192 static int active_area[4];
 193 
 194 dir_entry ifd1[]={
 195     {0xFE,   T_LONG,       1,  0},                                 // NewSubFileType: Main Image
 196     {0x100,  T_LONG|T_PTR, 1,  (int)&camera_sensor.raw_rowpix},    // ImageWidth
 197     {0x101,  T_LONG|T_PTR, 1,  (int)&camera_sensor.raw_rows},      // ImageLength
 198     {0x102,  T_SHORT|T_PTR,1,  (int)&camera_sensor.bits_per_pixel},// BitsPerSample
 199     {0x103,  T_SHORT,      1,  1},                                 // Compression: Uncompressed
 200     {0x106,  T_SHORT,      1,  0x8023},                            // PhotometricInterpretation: CFA
 201     {0x111,  T_LONG,       1,  0},                                 // StripOffsets: Offset
 202     {0x115,  T_SHORT,      1,  1},                                 // SamplesPerPixel: 1
 203     {0x116,  T_SHORT|T_PTR,1,  (int)&camera_sensor.raw_rows},      // RowsPerStrip
 204     {0x117,  T_LONG|T_PTR, 1,  (int)&camera_sensor.raw_size},      // StripByteCounts = CHDK RAW size
 205     {0x11A,  T_RATIONAL,   1,  (int)cam_Resolution},               // XResolution
 206     {0x11B,  T_RATIONAL,   1,  (int)cam_Resolution},               // YResolution
 207     {0x11C,  T_SHORT,      1,  1},                                 // PlanarConfiguration: 1
 208     {0x128,  T_SHORT,      1,  2},                                 // ResolutionUnit: inch
 209     {0x828D, T_SHORT,      2,  0x00020002},                        // CFARepeatPatternDim: Rows = 2, Cols = 2
 210     {0x828E, T_BYTE|T_PTR, 4,  (int)&camera_sensor.cfa_pattern},
 211     {0xC61A, T_LONG|T_PTR, 1,  (int)&camera_sensor.black_level},   // BlackLevel
 212     {0xC61D, T_LONG|T_PTR, 1,  (int)&camera_sensor.white_level},   // WhiteLevel
 213     {0xC61F, T_LONG,       2,  (int)&crop_origin},
 214     {0xC620, T_LONG,       2,  (int)&crop_size},
 215     {0xC68D, T_LONG,       4,  (int)&active_area},
 216     {0xC740, T_UNDEFINED|T_PTR, sizeof(badpixel_opcode),  (int)&badpixel_opcode},
 217     {0, T_EOL, 0, 0},
 218 };
 219 
 220 // Tags of specific entries in exif_ifd below.
 221 #define EXPOSURE_PROGRAM_TAG        0x8822
 222 #define METERING_MODE_TAG           0x9207
 223 #define FLASH_MODE_TAG              0x9209
 224 #define SSTIME_TAG                  0x9290
 225 #define SSTIME_ORIG_TAG             0x9291
 226 
 227 dir_entry exif_ifd[]={
 228     {0x829A, T_RATIONAL,   1,  (int)cam_shutter},          // Shutter speed
 229     {0x829D, T_RATIONAL,   1,  (int)cam_aperture},         // Aperture
 230     {0x8822, T_SHORT,      1,  0},                         // ExposureProgram
 231     {0x8827, T_SHORT|T_PTR,1,  (int)&exif_data.iso},       // ISOSpeedRatings
 232     {0x9000, T_UNDEFINED,  4,  0x31323230},                // ExifVersion: 2.21
 233     {0x9003, T_ASCII,      20, (int)cam_datetime},         // DateTimeOriginal
 234     {0x9201, T_SRATIONAL,  1,  (int)cam_apex_shutter},     // ShutterSpeedValue (APEX units)
 235     {0x9202, T_RATIONAL,   1,  (int)cam_apex_aperture},    // ApertureValue (APEX units)
 236     {0x9204, T_SRATIONAL,  1,  (int)cam_exp_bias},         // ExposureBias
 237     {0x9205, T_RATIONAL,   1,  (int)cam_max_av},           // MaxApertureValue
 238     {0x9206, T_RATIONAL,   1,  (int)cam_subject_distance}, // SubjectDistance
 239     {0x9207, T_SHORT,      1,  0},                         // Metering mode
 240     {0x9209, T_SHORT,      1,  0},                         // Flash mode
 241     {0x920A, T_RATIONAL,   1,  (int)cam_focal_length},     // FocalLength
 242     {0x9290, T_ASCII|T_PTR,4,  (int)cam_subsectime},       // DateTime milliseconds
 243     {0x9291, T_ASCII|T_PTR,4,  (int)cam_subsectime},       // DateTimeOriginal milliseconds
 244     {0xA405, T_SHORT|T_PTR,1,  (int)&exif_data.effective_focal_length},    // FocalLengthIn35mmFilm
 245     {0, T_EOL, 0, 0},
 246 };
 247 
 248 tGPS gps_data;
 249 
 250 dir_entry gpd_ifd[]={
 251     {0x0000, T_BYTE,              4,  0x00000302},                    //GPSVersionID: 2 3 0 0
 252     {0x0001, T_ASCII|T_PTR,       2,  (int)gps_data.latitudeRef},     //North or South Latitude "N\0" or "S\0"
 253     {0x0002, T_RATIONAL,          3,  (int)gps_data.latitude},        //Latitude
 254     {0x0003, T_ASCII|T_PTR,       2,  (int)gps_data.longitudeRef},    //East or West Latitude "E\0" or "W\0"
 255     {0x0004, T_RATIONAL,          3,  (int)gps_data.longitude},       //Longitude
 256     {0x0005, T_BYTE|T_PTR,        1,  (int)&gps_data.heightRef},      //AltitudeRef
 257     {0x0006, T_RATIONAL,          1,  (int)gps_data.height},          //Altitude
 258     {0x0007, T_RATIONAL,          3,  (int)gps_data.timeStamp},       //TimeStamp
 259     {0x0009, T_ASCII|T_PTR,       2,  (int)gps_data.status},          //Status
 260     //{0x000A, T_ASCII,             1,  0},                             //MeasureMode
 261     {0x0012, T_ASCII,             7,  (int)gps_data.mapDatum},        //MapDatum 7 + 1 pad byte
 262     {0x001D, T_ASCII,             11, (int)gps_data.dateStamp},       //DateStamp 11 + 1 pad byte
 263     {0, T_EOL, 0, 0},
 264 };
 265 
 266 int get_type_size(int type)
 267 {
 268     switch(type & 0xFF)
 269     {
 270     case T_BYTE:
 271     case T_SBYTE:
 272     case T_UNDEFINED:
 273     case T_ASCII:     return 1; 
 274     case T_SHORT:
 275     case T_SSHORT:    return 2;
 276     case T_LONG:
 277     case T_SLONG:
 278     case T_FLOAT:     return 4;
 279     case T_RATIONAL:
 280     case T_SRATIONAL:
 281     case T_DOUBLE:    return 8;
 282     default:          return 0;
 283     }
 284 }
 285 
 286 // IFD types and flags
 287 #define IFD_0       1
 288 #define IFD_1       2
 289 #define IFD_EXIF    3
 290 #define IFD_GPS     4
 291 #define IFD_SKIP    0x200       // Set this flag to prevent saving entry to file (used to block GPS if not needed)
 292 #define IFD_TYPE_MASK 0xF       // to mask out skip flag 
 293 
 294 typedef struct
 295 {
 296     dir_entry* entry;           // List of entries
 297     short count;                // Number of entries to be saved
 298     short type;                 // Type & flags
 299 } ifd_entry;
 300 
 301 ifd_entry ifd_list[] =
 302 {
 303     {ifd0,      0, IFD_0},
 304     {ifd1,      0, IFD_1},
 305     {exif_ifd,  0, IFD_EXIF},
 306     {gpd_ifd,   0, IFD_GPS},
 307     {0,0,0},
 308 };
 309 
 310 // Find an entry in the ifd_list array and return pointer
 311 static ifd_entry* get_ifd(int type)
 312 {
 313     int i;
 314     for (i = 0; ifd_list[i].entry != 0; i++)
 315     {
 316         if ((ifd_list[i].type & IFD_TYPE_MASK) == type)
 317             return &ifd_list[i];
 318     }
 319     return 0;
 320 }
 321 
 322 // Find a tag by IFD and TAG id, return pointer
 323 static dir_entry* get_tag(int ifd, int tag)
 324 {
 325     ifd_entry* p = get_ifd(ifd);
 326     if (p)
 327     {
 328         int i;
 329         for (i=0; p->entry[i].type != T_EOL; i++)
 330         {
 331             if (p->entry[i].tag == tag)
 332                 return &p->entry[i];
 333         }
 334     }
 335     return 0;
 336 }
 337 
 338 #define TIFF_HDR_SIZE (8)
 339 
 340 char* dng_header_buf = 0;
 341 int dng_header_buf_size;
 342 int dng_header_buf_offset;
 343 char *thumbnail_buf = 0;
 344 
 345 // Helper functions
 346 
 347 // Add something to the DNG header buffer, and increment size
 348 void add_to_buf(void* var, int size)
 349 {
 350     memcpy(dng_header_buf+dng_header_buf_offset,var,size);
 351     dng_header_buf_offset += size;
 352 }
 353 
 354 // Add something to the DNG header buffer, and increment size
 355 void add_val_to_buf(int val, int size)
 356 {
 357     add_to_buf(&val,size);
 358 }
 359 
 360 // Iterate over all IFDs in ifd_list, call 'f' function for any that are not skipped
 361 static void process_ifd_list(void (*f)(ifd_entry*))
 362 {
 363     int i;
 364     for (i=0; ifd_list[i].type!=0; i++)
 365     {
 366         if ((ifd_list[i].type & IFD_SKIP) == 0)
 367         {
 368             f(&ifd_list[i]);
 369         }
 370     }
 371 }
 372 
 373 // Iterate over all entries in an IFD, call 'f' function for any that are not skipped
 374 static void process_entries(ifd_entry* ifd, void (*f)(ifd_entry*, dir_entry*))
 375 {
 376     int i;
 377     for (i=0; ifd->entry[i].type != T_EOL; i++)
 378     {
 379         if ((ifd->entry[i].type & T_SKIP) == 0)  // Exclude skipped entries (e.g. GPS info if camera doesn't have GPS)
 380         {
 381             f(ifd, &ifd->entry[i]);
 382         }
 383     }
 384 }
 385 
 386 // Functions to count the number of valid (non-skipped) entries in an IFD
 387 // (called via process_ifd_list & process_entries)
 388 static void inc_ifd_count(ifd_entry* ifd, dir_entry* e)
 389 {
 390     ifd->count++;
 391 }
 392 
 393 static void calc_ifd_count(ifd_entry* ifd)
 394 {
 395     ifd->count = 0;
 396     process_entries(ifd, inc_ifd_count);
 397 }
 398 
 399 // Functions to calculate the offset to the raw data
 400 // (called via process_ifd_list & process_entries)
 401 static int raw_offset;
 402 
 403 static void inc_raw_offset(ifd_entry* ifd, dir_entry* e)
 404 {
 405     raw_offset += 12; // IFD directory entry size
 406     int size_ext = get_type_size(e->type) * e->count;
 407     if (size_ext > 4) raw_offset += size_ext + (size_ext&1);
 408 }
 409 
 410 static void calc_raw_offset(ifd_entry* ifd)
 411 {
 412     raw_offset+=6; // IFD header+footer
 413     process_entries(ifd, inc_raw_offset);   // Add size of each entry to raw_offset
 414 }
 415 
 416 // Function to calculate the offset to extra data to be saved
 417 // (called via process_ifd_list)
 418 static int extra_offset;
 419 
 420 static void calc_extra_offset(ifd_entry* ifd)
 421 {
 422     extra_offset += 6 + ifd->count * 12; // IFD header+footer
 423 }
 424 
 425 // Functions to add the IFDs and IFD entries to the save buffer
 426 // (called via process_ifd_list & process_entries)
 427 static void add_entry_to_buffer(ifd_entry* ifd, dir_entry* e)
 428 {
 429     add_val_to_buf(e->tag, sizeof(short));
 430     add_val_to_buf(e->type & 0xFF, sizeof(short));
 431     add_val_to_buf(e->count, sizeof(int));
 432     int size_ext = get_type_size(e->type) * e->count;
 433     if (size_ext <= 4)
 434     {
 435         if (e->type & T_PTR)
 436         {
 437             add_to_buf((void*)e->offset, sizeof(int));
 438         }
 439         else
 440         {
 441             add_val_to_buf(e->offset, sizeof(int));
 442         }
 443     }
 444     else
 445     {
 446         add_val_to_buf(extra_offset, sizeof(int));
 447         extra_offset += size_ext + (size_ext&1);
 448     }
 449 }
 450 
 451 static void add_ifd_to_buffer(ifd_entry* ifd)
 452 {
 453     add_val_to_buf(ifd->count, sizeof(short));  // Add count of entries for this IFD
 454     process_entries(ifd, add_entry_to_buffer);  // Add all entries
 455     add_val_to_buf(0, sizeof(int));             // Terminate entry list
 456 }
 457 
 458 // Functions to add the extra data to the save buffer
 459 // (called via process_ifd_list & process_entries)
 460 static void add_entry_extra_data_to_buffer(ifd_entry* ifd, dir_entry* e)
 461 {
 462     int size_ext = get_type_size(e->type) * e->count;
 463     if (size_ext > 4)
 464     {
 465         add_to_buf((void*)e->offset, size_ext);
 466         if (size_ext&1) add_val_to_buf(0, 1);
 467     }
 468 }
 469 
 470 static void add_extra_data_to_buffer(ifd_entry* ifd)
 471 {
 472     process_entries(ifd, add_entry_extra_data_to_buffer);
 473 }
 474 
 475 /*
 476 create a dng header, including space for thumbnail if required
 477 if ver1_1 set, creates a dng 1.1 header, otherwise a 1.3 header (matching conf.dng_version)
 478 if minimal is set, don't pad to 512 byte boundery or create thumbnail
 479 */
 480 
 481 void create_dng_header(int ver1_1, int minimal)
 482 {
 483     int i,j;
 484 
 485     // Set version and opcodes
 486     if (ver1_1)
 487     {
 488         // If CHDK is removing bad pixels then set DNG version to 1.1 and remove opcodes
 489         get_tag(IFD_0, DNG_VERSION_TAG)->offset = BE(0x01010000);
 490         get_tag(IFD_1, BADPIXEL_OPCODE_TAG)->type |= T_SKIP;
 491     }
 492     else
 493     {
 494         // Set DNG version to 1.3 and add bad pixel opcodes
 495         get_tag(IFD_0, DNG_VERSION_TAG)->offset = BE(0x01030000);
 496         get_tag(IFD_1, BADPIXEL_OPCODE_TAG)->type &= ~T_SKIP;
 497         // Set CFAPattern value
 498         switch (camera_sensor.cfa_pattern)
 499         {
 500         case 0x02010100:
 501             badpixel_opcode[BADPIX_CFA_INDEX] = BE(0);              // BayerPhase = 0 (top left pixel is red)
 502             break;
 503         case 0x01020001:
 504             badpixel_opcode[BADPIX_CFA_INDEX] = BE(1);              // BayerPhase = 1 (top left pixel is green in a green/red row)
 505             break;
 506         case 0x01000201:
 507             badpixel_opcode[BADPIX_CFA_INDEX] = BE(2);              // BayerPhase = 2 (top left pixel is green in a green/blue row)
 508             break;
 509         case 0x00010102:
 510             badpixel_opcode[BADPIX_CFA_INDEX] = BE(3);              // BayerPhase = 3 (top left pixel is blue)
 511             break;
 512         }
 513     }
 514 
 515     // Set crop origin, size and active area from user selected 'crop size'
 516     switch (conf.dng_crop_size)
 517     {
 518         case 0:     // JPEG
 519         default:
 520             // Set crop origin & size
 521             crop_origin[0] = camera_sensor.jpeg.x;
 522             crop_origin[1] = camera_sensor.jpeg.y;
 523             crop_size[0] = camera_sensor.jpeg.width;
 524             crop_size[1] = camera_sensor.jpeg.height;
 525             // Re-set active area (in case user has changed setting)
 526             memcpy(active_area, camera_sensor.dng_active_area, sizeof(active_area));
 527             break;
 528         case 1:     // Active Area
 529             // Set crop origin & size
 530             crop_origin[0] = 0;
 531             crop_origin[1] = 0;
 532             crop_size[0] = camera_sensor.active_area.x2 - camera_sensor.active_area.x1;
 533             crop_size[1] = camera_sensor.active_area.y2 - camera_sensor.active_area.y1;
 534             // Re-set active area (in case user has changed setting)
 535             memcpy(active_area, camera_sensor.dng_active_area, sizeof(active_area));
 536             break;
 537         case 2:     // Full sensor
 538             // Set crop origin & size
 539             crop_origin[0] = 0;
 540             crop_origin[1] = 0;
 541             crop_size[0] = camera_sensor.raw_rowpix;
 542             crop_size[1] = camera_sensor.raw_rows;
 543             // Re-set active area (in case user has changed setting)
 544             active_area[0] = (camera_sensor.active_area.y1 & 1);    // In case active area top is an odd value, otherwise CFA pattern will be wrong
 545             active_area[1] = 0;
 546             active_area[2] = camera_sensor.raw_rows;
 547             active_area[3] = camera_sensor.raw_rowpix;
 548             break;
 549     }
 550 
 551     // filling EXIF fields
 552 
 553     if (camera_info.props.gps)
 554     {
 555         // If camera has GPS get the GPS data
 556         get_property_case(camera_info.props.gps, &gps_data, sizeof(gps_data));
 557     }
 558     else
 559     {
 560         // If no GPS then remove the GPS data from the header
 561         get_ifd(IFD_GPS)->type |= IFD_SKIP;
 562         get_tag(IFD_0, GPS_IFD_TAG)->type |= T_SKIP;         // mark entry so it is skipped
 563     }
 564 
 565     // Fix the counts and offsets where needed
 566 
 567     get_tag(IFD_0, CAMERA_NAME_TAG)->count = get_tag(IFD_0, UNIQUE_CAMERA_MODEL_TAG)->count = strlen(cam_name) + 1;
 568     get_tag(IFD_0, CHDK_VER_TAG)->offset = (int)camera_info.chdk_dng_ver;
 569     get_tag(IFD_0, CHDK_VER_TAG)->count = strlen(camera_info.chdk_dng_ver) + 1;
 570     get_tag(IFD_0, ARTIST_NAME_TAG)->count = strlen(artist_name) + 1;
 571     get_tag(IFD_0, COPYRIGHT_TAG)->count = strlen(copyright) + 1;
 572     get_tag(IFD_0, ORIENTATION_TAG)->offset = get_orientation_for_exif(exif_data.orientation);
 573 
 574     get_tag(IFD_EXIF, EXPOSURE_PROGRAM_TAG)->offset = get_exp_program_for_exif(exif_data.exp_program);
 575     get_tag(IFD_EXIF, METERING_MODE_TAG)->offset = get_metering_mode_for_exif(exif_data.metering_mode);
 576     get_tag(IFD_EXIF, FLASH_MODE_TAG)->offset = get_flash_mode_for_exif(exif_data.flash_mode, exif_data.flash_fired);
 577     get_tag(IFD_EXIF, SSTIME_TAG)->count = get_tag(IFD_EXIF, SSTIME_ORIG_TAG)->count = strlen(cam_subsectime)+1;
 578 
 579     // Skip color matrix and calibration entries that aren't defined for the camera
 580     if (camera_sensor.calibration_illuminant2 == 0)
 581     {
 582         get_tag(IFD_0, ILLUMINANT2_TAG)->type |= T_SKIP;
 583         get_tag(IFD_0, COLOR_MATRIX2_TAG)->type |= T_SKIP;
 584     }
 585     if (camera_sensor.has_calibration1 == 0)    get_tag(IFD_0, CALIBRATION1_TAG)->type |= T_SKIP;
 586     if (camera_sensor.has_calibration2 == 0)    get_tag(IFD_0, CALIBRATION2_TAG)->type |= T_SKIP;
 587     if (camera_sensor.has_forwardmatrix1 == 0)  get_tag(IFD_0, FORWARD_MATRIX1_TAG)->type |= T_SKIP;
 588     if (camera_sensor.has_forwardmatrix2 == 0)  get_tag(IFD_0, FORWARD_MATRIX2_TAG)->type |= T_SKIP;
 589 
 590     // fixup up IFD count values, exclude skipped entries
 591     process_ifd_list(calc_ifd_count);
 592 
 593     // calculating offset of RAW data and count of entries for each IFD
 594     raw_offset = TIFF_HDR_SIZE;
 595     process_ifd_list(calc_raw_offset);
 596 
 597     // creating buffer for writing data
 598     if (minimal)
 599     {
 600         raw_offset = (raw_offset/4+1)*4; // ensure 32 bit aligned
 601         dng_header_buf = malloc(raw_offset);
 602         thumbnail_buf = NULL;
 603     }
 604     else
 605     {
 606         raw_offset = (raw_offset/512+1)*512; // exclusively for CHDK fast file writing
 607         dng_header_buf = malloc(raw_offset + DNG_TH_BYTES);
 608         thumbnail_buf = dng_header_buf + raw_offset;
 609     }
 610     dng_header_buf_size = raw_offset;
 611     if (!dng_header_buf)
 612     {
 613         thumbnail_buf = NULL;
 614         return;
 615     }
 616     dng_header_buf_offset = 0;
 617 
 618     //  writing offsets for EXIF IFD and RAW data and calculating offset for extra data
 619 
 620     get_tag(IFD_0, SUBIFDS_TAG)->offset = TIFF_HDR_SIZE + ifd_list[0].count * 12 + 6;                            // SubIFDs offset
 621     get_tag(IFD_0, EXIF_IFD_TAG)->offset = TIFF_HDR_SIZE + (ifd_list[0].count + ifd_list[1].count) * 12 + 6 + 6; // EXIF IFD offset
 622     if (camera_info.props.gps)
 623         get_tag(IFD_0, GPS_IFD_TAG)->offset = TIFF_HDR_SIZE + (ifd_list[0].count + ifd_list[1].count + ifd_list[2].count) * 12 + 6 + 6 + 6;  // GPS IFD offset
 624 
 625     get_tag(IFD_0, THUMB_DATA_TAG)->offset = raw_offset;                 //StripOffsets for thumbnail
 626     get_tag(IFD_1, RAW_DATA_TAG)->offset = raw_offset + DNG_TH_BYTES;    //StripOffsets for main image
 627 
 628     extra_offset=TIFF_HDR_SIZE;
 629     process_ifd_list(calc_extra_offset);
 630 
 631     // TIFF file header
 632     add_val_to_buf(0x4949, sizeof(short));      // little endian
 633     add_val_to_buf(42, sizeof(short));          // An arbitrary but carefully chosen number that further identifies the file as a TIFF file.
 634     add_val_to_buf(TIFF_HDR_SIZE, sizeof(int)); // offset of first IFD
 635 
 636     // writing IFDs
 637     process_ifd_list(add_ifd_to_buffer);
 638 
 639     // writing extra data (values for entries that don't fit into 4 bytes)
 640     process_ifd_list(add_extra_data_to_buffer);
 641 
 642     // writing zeros to tail of DNG header (just for fun)
 643     for (i=dng_header_buf_offset; i<dng_header_buf_size; i++) dng_header_buf[i]=0;
 644 }
 645 
 646 void free_dng_header(void)
 647 {
 648     if (dng_header_buf)
 649     {
 650         free(dng_header_buf);
 651         dng_header_buf = NULL;
 652     }
 653 }
 654 
 655 // Helper functions - convert camera settings to EXIF values
 656 unsigned short get_exp_program_for_exif(int exp_program)
 657 {
 658     switch(exp_program)
 659     {
 660     case MODE_M: return 1;
 661     case MODE_P: return 2;
 662     case MODE_AV: return 3;
 663     case MODE_TV: return 4;
 664     default: return 0;
 665     }
 666 }
 667 
 668 unsigned short get_orientation_for_exif(short orientation)
 669 {
 670     switch(orientation)
 671     {
 672     case  90: return 6;  // Right  - Top
 673     case 180: return 3;  // Bottom - Right
 674     case 270: return 8;  // Left   - Bottom
 675     case   0:            // Top    - Left
 676     default : return 1;
 677     }
 678 }
 679 
 680 unsigned short get_flash_mode_for_exif(short mode, short fired){
 681     fired&=1;
 682     switch(mode)
 683     {
 684     case 0: return (3<<3)|fired; // auto
 685     case 1: return (1<<3)|fired; // on
 686     case 2: return (2<<3)|fired; // off
 687     default: return fired;
 688     }
 689 }
 690 
 691 unsigned short get_metering_mode_for_exif(short metering_mode)
 692 {
 693     switch (metering_mode)
 694     {
 695     case 0: return 5; // Evaluative
 696     case 1: return 3; // Spot
 697     case 2: return 2; // CenterWeightedAverage
 698     default: return 255; // other
 699     }
 700 }
 701 
 702 int pow_calc_2( int mult, int x, int x_div, double y, int y_div)
 703 {
 704         double x1 = x;
 705         if ( x_div != 1 ) { x1=x1/x_div;}
 706         if ( y_div != 1 ) { y=y/y_div;}
 707 
 708         if ( mult==1 )
 709                 return pow( x1, y );
 710                 else
 711                 return mult     * pow( x1, y );
 712 }
 713 
 714 int pow_calc( int mult, int x, int x_div, int y, int y_div)
 715 {
 716         return pow_calc_2( mult, x, x_div, y, y_div);
 717 }
 718 
 719 // Get EXIF values from camera
 720 void capture_data_for_exif(void)
 721 {
 722     short short_prop_val;
 723     time_t datetime;
 724     long subsectime;
 725     struct tm *ttm;
 726     int wb[3];
 727 
 728     exif_data.iso=shooting_get_iso_market();
 729 
 730     // Shutter speed tags
 731     get_property_case(camera_info.props.tv, &short_prop_val, sizeof(short_prop_val));
 732     cam_shutter[0]      = pow_calc( 1000000, 2, 1, -short_prop_val, 96);
 733     cam_apex_shutter[0] = short_prop_val;
 734 
 735     // Date & time tag (note - uses shutter speed from 'short_prop_val' code above)
 736     if (camera_info.state.shutter_open_time)
 737     {
 738         // milliseconds component of shutter_open_time
 739         subsectime = (camera_info.state.shutter_open_tick_count - camera_info.tick_count_offset) % 1000;
 740         // shutter closing time
 741         datetime = camera_info.state.shutter_open_time + ((cam_shutter[0] + (subsectime * 1000)) / 1000000);
 742         camera_info.state.shutter_open_time = 0;
 743     }
 744     else
 745     {
 746         datetime = time(NULL);
 747         // milliseconds component of datetime
 748         subsectime = (get_tick_count() - camera_info.tick_count_offset) % 1000;
 749     }
 750     ttm = localtime(&datetime);
 751     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);
 752     sprintf(cam_subsectime, "%02d", subsectime/10);     // camera tick count is only accurate to 10 msec intervals
 753 
 754     get_property_case(camera_info.props.av, &short_prop_val, sizeof(short_prop_val));
 755     cam_aperture[0]      = pow_calc( 10, 2, 1, short_prop_val, 192);
 756     cam_apex_aperture[0] = short_prop_val;
 757 
 758     get_property_case(camera_info.props.min_av, &short_prop_val, sizeof(short_prop_val));
 759     cam_max_av[0] = short_prop_val;
 760 
 761     get_property_case(camera_info.props.ev_correction_2, &short_prop_val, sizeof(short_prop_val));
 762     cam_exp_bias[0] = short_prop_val;
 763 
 764     exif_data.exp_program = camera_info.state.mode_shooting;
 765 
 766     cam_subject_distance[0] = shooting_get_exif_subject_dist();
 767 
 768     cam_focal_length[0] = get_focal_length(shooting_get_zoom());
 769     exif_data.effective_focal_length = get_effective_focal_length(shooting_get_zoom()) / 1000;
 770 
 771     get_property_case(camera_info.props.orientation_sensor, &exif_data.orientation, sizeof(exif_data.orientation));
 772     get_parameter_data(camera_info.params.camera_name, &cam_name, sizeof(cam_name));
 773     if (camera_info.params.artist_name) get_parameter_data(camera_info.params.artist_name, &artist_name, sizeof(artist_name));
 774     else if (camera_info.params.owner_name) get_parameter_data(camera_info.params.owner_name, &artist_name, 32);
 775     if (camera_info.params.copyright) get_parameter_data(camera_info.params.copyright, &copyright, sizeof(copyright));
 776     get_property_case(camera_info.props.flash_mode, &exif_data.flash_mode, sizeof(exif_data.flash_mode));
 777     get_property_case(camera_info.props.flash_fire, &exif_data.flash_fired, sizeof(exif_data.flash_fired));
 778     get_property_case(camera_info.props.metering_mode, &exif_data.metering_mode, sizeof(exif_data.metering_mode));
 779 
 780     get_property_case(camera_info.props.wb_adj, &wb, sizeof(wb));  
 781     cam_AsShotNeutral[1]=wb[1];
 782     cam_AsShotNeutral[3]=wb[0];
 783     cam_AsShotNeutral[5]=wb[2];
 784 }
 785 
 786 //-------------------------------------------------------------------
 787 
 788 static int convert_dng_to_chdk_raw(char* fn)
 789 {
 790 #define BUF_SIZE (32768)
 791     FILE *dng, *raw;
 792     int *buf;
 793     int i;
 794     struct stat st;
 795     struct utimbuf t;
 796 
 797     if (stat(fn, &st) != 0 || st.st_size<=camera_sensor.raw_size)
 798         return 0;
 799 
 800     running = 1;
 801 
 802     buf=malloc(BUF_SIZE);
 803     if (buf)
 804     {
 805         started();
 806         dng=fopen(fn,"rb");
 807         if (dng)
 808         {
 809             fread(buf, 1, 8, dng);
 810             if (buf[0]==0x2A4949 && buf[1]==8)
 811             {  // chdk dng header
 812                 i=strlen(fn)-3;
 813                 if (strncmp(fn+i,"CR",2)==0) strcpy(fn+i,"WAV"); else strcpy(fn+i,"CRW");
 814                 raw=fopen(fn,"w+b");
 815                 if (raw){
 816                     fseek(dng, st.st_size-camera_sensor.raw_size, SEEK_SET); // SEEK_END is not working?
 817                     for (i=0; i<camera_sensor.raw_size/BUF_SIZE; i++)
 818                     {
 819                         fread(buf, 1, BUF_SIZE, dng);
 820                         reverse_bytes_order2((char*)buf, (char*)buf, BUF_SIZE);
 821                         fwrite(buf, 1, BUF_SIZE, raw);
 822                     }
 823                     fread(buf, 1, camera_sensor.raw_size%BUF_SIZE, dng);
 824                     reverse_bytes_order2((char*)buf, (char*)buf, camera_sensor.raw_size%BUF_SIZE);
 825                     fwrite(buf, 1, camera_sensor.raw_size%BUF_SIZE, raw);
 826                     fclose(raw);
 827                     t.actime = t.modtime = time(NULL);
 828                     utime(fn, &t);
 829                 } // if (raw)
 830             } // if chdk dng header
 831             fclose(dng);
 832         } //if (dng)
 833         free(buf);
 834         finished();
 835     }  //if (buf)
 836 
 837     running = 0;
 838 
 839     return 1;
 840 }
 841 
 842 static void load_dng_to_rawbuffer(char *fn, char *rawadr)
 843 {
 844     running = 1;
 845 
 846     struct stat st;
 847     if ((stat(fn,&st) == 0) && (st.st_size >= camera_sensor.raw_size))
 848     {
 849         int fd = open(fn, O_RDONLY, 0777);
 850         if (fd >= 0)
 851         {
 852             lseek(fd, st.st_size-camera_sensor.raw_size, SEEK_SET);
 853             read(fd, rawadr, camera_sensor.raw_size);
 854             close(fd);
 855             reverse_bytes_order2(rawadr, rawadr, camera_sensor.raw_size);
 856         }
 857     }
 858 
 859     running = 0;
 860 }
 861 
 862 //-------------------------------------------------------------------
 863 // Functions for creating DNG thumbnail image
 864 
 865 
 866 // original code to generate the gamma buf
 867 /*
 868 static unsigned char gamma[256];
 869 void fill_gamma_buf(void)
 870 {
 871     int i;
 872     if (gamma[255]) return;
 873     for (i=0; i<12; i++) gamma[i]=pow_calc_2(255, i, 255, 0.5, 1);
 874     for (i=12; i<64; i++) gamma[i]=pow_calc_2(255, i, 255, 0.4, 1);
 875     for (i=64; i<=255; i++) gamma[i]=pow_calc_2(255, i, 255, 0.25, 1);
 876 }
 877 */
 878 
 879 static const unsigned char gamma[256] =
 880 {
 881 0,15,22,27,31,35,39,42,45,47,50,52,75,77,79,82,
 882 84,86,88,90,92,93,95,97,99,100,102,103,105,106,108,109,
 883 111,112,113,115,116,117,119,120,121,122,123,125,126,127,128,129,
 884 130,131,132,133,134,136,137,138,139,140,141,141,142,143,144,145,
 885 180,181,181,182,183,183,184,185,185,186,187,187,188,189,189,190,
 886 190,191,192,192,193,193,194,194,195,195,196,197,197,198,198,199,
 887 199,200,200,201,201,202,202,203,203,204,204,205,205,206,206,207,
 888 207,208,208,208,209,209,210,210,211,211,212,212,212,213,213,214,
 889 214,215,215,215,216,216,217,217,217,218,218,219,219,219,220,220,
 890 221,221,221,222,222,222,223,223,224,224,224,225,225,225,226,226,
 891 226,227,227,228,228,228,229,229,229,230,230,230,231,231,231,232,
 892 232,232,233,233,233,234,234,234,235,235,235,235,236,236,236,237,
 893 237,237,238,238,238,239,239,239,239,240,240,240,241,241,241,242,
 894 242,242,242,243,243,243,244,244,244,244,245,245,245,246,246,246,
 895 246,247,247,247,247,248,248,248,249,249,249,249,250,250,250,250,
 896 251,251,251,251,252,252,252,252,253,253,253,253,254,254,254,255
 897 };
 898 void create_thumbnail()
 899 {
 900     char *buf = thumbnail_buf;
 901     int shift = camera_sensor.bits_per_pixel - 8;
 902 
 903     int x_inc = camera_sensor.jpeg.width / DNG_TH_WIDTH;
 904     int y_inc = camera_sensor.jpeg.height / DNG_TH_HEIGHT;
 905 
 906     int x_end = camera_sensor.active_area.x1 + camera_sensor.jpeg.x + DNG_TH_WIDTH*x_inc;
 907     int y_end = camera_sensor.active_area.y1 + camera_sensor.jpeg.y + DNG_TH_HEIGHT*y_inc;
 908 
 909     int x_off,y_off;
 910 
 911     // The sensor bayer patterns are:
 912     //  0x02010100  0x01000201  0x01020001
 913     //      R G         G B         G R
 914     //      G B         R G         B G
 915     // for the second pattern yadj shifts the thumbnail row down one line
 916     // for the third pattern xadj shifts the thumbnail row accross one pixel
 917     // these make the patterns the same
 918     int yadj = (camera_sensor.cfa_pattern == 0x01000201) ? 1 : 0;
 919     int xadj = (camera_sensor.cfa_pattern == 0x01020001) ? 1 : 0;
 920 
 921     for (y_off=camera_sensor.active_area.y1 + camera_sensor.jpeg.y; y_off<y_end; y_off += y_inc)
 922         for (x_off=camera_sensor.active_area.x1 + camera_sensor.jpeg.x; x_off<x_end; x_off += x_inc)
 923         {
 924             int x = (x_off & 0xFFFFFFFE) + xadj;
 925             int y = (y_off & 0xFFFFFFFE) + yadj;
 926 
 927             *buf++ = gamma[get_raw_pixel(x,y)>>shift];           // red pixel
 928             //*buf++ = gamma[6*(get_raw_pixel(x+1,y)>>shift)/10];  // green pixel
 929             int g=get_raw_pixel(x+1,y) >> (shift+1);
 930             *buf++ = gamma[g+(g>>2)];  // green pixel was (6*g/10), now (g/2 + g/8)
 931             *buf++ = gamma[get_raw_pixel(x+1,y+1)>>shift];       // blue pixel
 932         }
 933 }
 934 
 935 //-------------------------------------------------------------------
 936 // Functions for handling DNG bad pixel file creation and bad pixel
 937 // removal from images.
 938 
 939 #define INIT_BADPIXEL_COUNT -1
 940 #define INIT_BADPIXEL_FILE -2
 941 
 942 #define PATH_BADPIXEL_BIN "A/CHDK/badpixel.bin"
 943 #define PATH_BAD_TMP_BIN "A/CHDK/bad_tmp.bin"
 944 
 945 int init_badpixel_bin_flag; // contants above to count/create file, > 0 num bad pixel
 946 
 947 int raw_init_badpixel_bin()
 948 {
 949     int count;
 950     unsigned int x, y, xlen, ylen;
 951     unsigned short c[9];
 952 
 953     FILE*f;
 954     if(init_badpixel_bin_flag == INIT_BADPIXEL_FILE)
 955     {
 956         f=fopen(PATH_BAD_TMP_BIN,"w+b");
 957     }
 958     else if (init_badpixel_bin_flag == INIT_BADPIXEL_COUNT)
 959     {
 960         f=NULL;
 961     }
 962     else
 963     {
 964         return 0;
 965     }
 966     count = 0;
 967     for (x=camera_sensor.active_area.x1; x<camera_sensor.active_area.x2; x++)
 968     {
 969         xlen = 0;
 970         for (y=camera_sensor.active_area.y1; y<camera_sensor.active_area.y2; y++)
 971         {
 972             if (get_raw_pixel(x,y) <= camera_sensor.dng_badpixel_value_limit)
 973             {
 974                 for (ylen=1; ylen<8 && (y+ylen)<camera_sensor.active_area.y2; ylen++)
 975                     if (get_raw_pixel(x,y+ylen) > camera_sensor.dng_badpixel_value_limit)
 976                         break;
 977                 if (f)
 978                 {
 979                     c[++xlen] = y | ((ylen-1) << 13);
 980                     if (xlen == 8)
 981                     {
 982                         c[0] = x | ((xlen-1) << 13);
 983                         fwrite(c, 2, xlen+1, f);
 984                         xlen = 0;
 985                     }
 986                 }
 987                 count = count + ylen;
 988                 y += ylen - 1;
 989             }
 990         }
 991         if (f && (xlen > 0))
 992         {
 993             c[0] = x | ((xlen-1) << 13);
 994             fwrite(c, 2, xlen+1, f);
 995         }
 996     }
 997     if (f) fclose(f);
 998     init_badpixel_bin_flag = count;
 999     camera_info.state.state_shooting_progress = SHOOTING_PROGRESS_PROCESSING;
1000     return 1;
1001 }
1002 
1003 short* binary_list=NULL;
1004 int binary_count=-1;
1005 
1006 void unload_bad_pixels_list_b(void)
1007 {
1008     if (binary_list) free(binary_list);
1009     binary_list=NULL;
1010     binary_count=-1;
1011 }
1012 
1013 void load_bad_pixels_list_b(char* filename)
1014 {
1015     struct stat st;
1016     long filesize;
1017     void* ptr;
1018     FILE *fd;
1019 
1020     if ( filename==0 )
1021     { 
1022         unload_bad_pixels_list_b();
1023         return;
1024     }
1025 
1026     binary_count=-1;
1027     if (stat(filename,&st)!=0) return;
1028     filesize=st.st_size;
1029     if (filesize%sizeof(short) != 0) return;
1030     if (filesize == 0) { binary_count = 0; return; }    // Allow empty badpixel.bin file
1031     ptr=malloc(filesize);
1032     if (!ptr) return;
1033     fd=fopen(filename, "rb");
1034     if (fd)
1035     {
1036         fread(ptr,1, filesize,fd);
1037         fclose(fd);
1038         binary_list=ptr;
1039         binary_count=filesize/sizeof(short);
1040     }
1041     else free(ptr);
1042 }
1043 
1044 void patch_bad_pixels_b(void)
1045 {
1046     int i;
1047     short* ptr=binary_list;
1048     short x, y, xcnt, ycnt;
1049     for (i=0; i<binary_count;)
1050     {
1051         x = ptr[i] & 0x1FFF;
1052         xcnt = (ptr[i] >> 13) & 7;
1053         i++;
1054         for (; xcnt>=0; xcnt--)
1055         {
1056             y = ptr[i] & 0x1FFF;
1057             ycnt = (ptr[i] >> 13) & 7;
1058             i++;
1059             for (; ycnt>=0; ycnt--, y++)
1060                 if (get_raw_pixel(x, y) <= camera_sensor.dng_badpixel_value_limit)
1061                     patch_bad_pixel(x, y);
1062         }
1063     }
1064 }
1065 
1066 int badpixel_list_loaded_b(void)
1067 {
1068     return (binary_count >= 0) ? 1 : 0;
1069 }
1070 
1071 // -----------------------------------------------
1072 
1073 static unsigned int badpix_cnt1;
1074 
1075 static int action_stack_BADPIX_S3()
1076 {
1077     action_pop_func(0);
1078     running = 0;
1079     return 1;
1080 }
1081 
1082 static int action_stack_BADPIX_S2()
1083 {
1084     // Process bad pixel generation actions
1085 
1086     action_pop_func(0);
1087 
1088     console_clear();
1089     if (badpix_cnt1 == init_badpixel_bin_flag)
1090     {
1091         // TODO script asked confirmation first
1092         // should sanity check bad pixel count at least,
1093         // wrong buffer address could make badpixel bigger than available mem
1094         char msg[32];
1095         console_add_line("badpixel.bin created.");
1096         sprintf(msg, "Bad pixel count: %d", badpix_cnt1);
1097         console_add_line(msg);
1098         remove(PATH_BADPIXEL_BIN);
1099         rename(PATH_BAD_TMP_BIN,PATH_BADPIXEL_BIN);
1100     }
1101     else
1102     {
1103         console_add_line("badpixel.bin failed.");
1104         console_add_line("Please try again.");
1105     }
1106     init_badpixel_bin_flag = 0;
1107     remove(PATH_BAD_TMP_BIN);
1108 
1109     // Delay to give user time to read messages
1110     action_push_func(action_stack_BADPIX_S3);
1111     action_push_delay(3000);
1112 
1113     return 1;
1114 }
1115 
1116 static int action_stack_BADPIX_S1()
1117 {
1118     // Process bad pixel generation actions
1119 
1120     action_pop_func(0);
1121 
1122     // Count bad pixels from previous shot
1123     badpix_cnt1 = init_badpixel_bin_flag;
1124     init_badpixel_bin_flag = INIT_BADPIXEL_FILE;
1125     shooting_set_tv96_direct(96, SET_LATER);
1126 
1127     // Push stack items for next phase (note reversed execution order)
1128     action_push_func(action_stack_BADPIX_S2);
1129     action_push_shoot(1);
1130 
1131     return 1;
1132 }
1133 
1134 static int action_stack_BADPIX_START()
1135 {
1136     // Process bad pixel generation actions
1137 
1138     action_pop_func(0);
1139 
1140     // Notify user
1141     console_clear();
1142     console_add_line("Wait please... ");
1143     console_add_line("This takes a few seconds,");
1144     console_add_line("don't panic!");
1145 
1146     init_badpixel_bin_flag = INIT_BADPIXEL_COUNT;
1147 
1148     shooting_set_tv96_direct(96, SET_LATER);
1149 
1150     // Push stack items for next phase (note reversed execution order)
1151     action_push_func(action_stack_BADPIX_S1);
1152     action_push_shoot(1);
1153     action_push_delay(3000);
1154 
1155     return 1;
1156 }
1157 
1158 void create_badpixel_bin()
1159 {
1160     if (!camera_info.state.mode_rec)
1161     {
1162         gui_mbox_init(LANG_ERROR, LANG_MSG_RECMODE_REQUIRED, MBOX_BTN_OK|MBOX_TEXT_CENTER, NULL);
1163         return;
1164     }
1165 
1166     running = 1;
1167 
1168     gui_set_mode(&altGuiHandler);
1169     // Create an action stack to generate bad pixels - start with action_stack_BADPIX_START func above
1170     action_stack_create(&action_stack_BADPIX_START);
1171 }
1172 
1173 // TODO we really only need done/not done so far
1174 #define RB_STAGE_DONE           0
1175 #define RB_STAGE_INIT           1
1176 #define RB_STAGE_REVERSING      2
1177 #define RB_STAGE_DEREVERSING    3
1178 
1179 /*
1180 chunk size to for reversing task.
1181 This defines the minimum increment that can be written in the writing task
1182 smaller sizes reduce the chance the writing task will have to wait for
1183 the initial reverse to finish, but increases the amount of time spent sleeping, 
1184 and may increase the number of writes
1185 From testing, 512kb appears to be a reasonable compromise
1186 */
1187 #define DNG_REV_CHUNK_SIZE  (512*1024)
1188 
1189 /*
1190 chunk size for writing final chunks of DNG
1191 only applicable to cameras with a single raw buffer
1192 defines the size of chunks write at the end of the raw data
1193 This this affects how well the reversing task can restore the buffer to
1194 original byte order in parallel with writing, and how much overhead there
1195 is for the final chunk.
1196 */
1197 #define DNG_END_CHUNK_SIZE (512*1024)
1198 
1199 /*
1200 number of minimum number of chunks to write at the end (single raw buffer cams only)
1201 */
1202 #define DNG_END_NUM_CHUNKS (3)
1203 
1204 static struct {
1205     // all pointers here are cached or uncached per user settings
1206     // the following 3 values are not modifed after initialization
1207     char *src; // intial src address
1208     char *dst; // initial dest address, may be same as src
1209     char *end; // end of dst
1210     // the following 3 track the state of the writing and reversing process
1211     char *reversed; // pointer to completed, set by reverse_bytes_task
1212     char *written; // pointer to written, set by main task
1213     int stage; // stage to detect when done
1214 } rb_state;
1215 
1216 void reverse_bytes_task() {
1217     char *src = rb_state.src;
1218     rb_state.stage = RB_STAGE_REVERSING;
1219     rb_state.reversed = rb_state.dst;
1220     // reverse byte order of frame buffer for DNG in chunks, to allow writing to proceed in parallel
1221     while(rb_state.reversed < rb_state.end) {
1222         int chunk_size;
1223         if(rb_state.reversed + DNG_REV_CHUNK_SIZE > rb_state.end) {
1224             chunk_size = rb_state.end - rb_state.reversed;
1225         } else {
1226             chunk_size = DNG_REV_CHUNK_SIZE;
1227         }
1228         reverse_bytes_order2(src, rb_state.reversed, chunk_size);
1229         src += chunk_size;
1230         rb_state.reversed += chunk_size;
1231         // seems to give slightly faster times with less variation
1232         // usually plenty of time to reverse, but in configurations with
1233         // slow camera + small sensor + fast card + single buffer
1234         // may cause some avoidable overhead
1235         msleep(10);
1236     }
1237     rb_state.stage = RB_STAGE_DEREVERSING;
1238     // if only a single raw buffer exists, restore the original byte order for
1239     // the portions of the buffer which have been written out, waiting as needed
1240     if(rb_state.src == rb_state.dst) {
1241         src = rb_state.src;
1242         int offset = 0;
1243         while(src < rb_state.end) {
1244             int chunk_size = rb_state.written - src;
1245             if(!chunk_size) {
1246                 msleep(10);
1247                 continue;
1248             }
1249             reverse_bytes_order2(src, src, chunk_size);
1250             src += chunk_size;
1251         }
1252         // if reverse was done on cached raw, 
1253         // clean cache so canon FW doesn't see reversed data in uncached
1254         if(ADR_IS_CACHED(rb_state.dst)) {
1255             dcache_clean_all();
1256         }
1257     }
1258 
1259 
1260     rb_state.stage = RB_STAGE_DONE;
1261     ExitTask();
1262 }
1263 
1264 //-------------------------------------------------------------------
1265 // Write DNG header, thumbnail and data to file
1266 
1267 
1268 int write_dng(char* rawadr, char* altrawadr) 
1269 {
1270     int fd;
1271 
1272     create_dng_header(conf.dng_version,0);
1273 
1274     if (!dng_header_buf) {
1275         return 0;
1276     }
1277 
1278     if (conf.dng_version)
1279         patch_bad_pixels_b();
1280 
1281     create_thumbnail();
1282 
1283     // TODO - sanity check that prevous task isn't hanging around
1284     if(rb_state.stage != RB_STAGE_DONE) {
1285         int i;
1286         for(i=0;i<50;i++) {
1287             debug_led(1);
1288             msleep(200);
1289             debug_led(0);
1290             msleep(200);
1291         }
1292         return 0;
1293     }
1294     rb_state.stage = RB_STAGE_INIT;
1295     rb_state.src = rawadr;
1296     rb_state.written = rb_state.reversed = rb_state.dst = altrawadr;
1297     rb_state.end = rb_state.dst + camera_sensor.raw_size;
1298 
1299     // task is created with lower priority than spytask (0x19) 
1300     // to improve chance of spytask getting control when write completes
1301     CreateTask("RevBytes",0x1A,0x400,reverse_bytes_task);
1302 
1303     fd = raw_createfile();
1304     if(fd < 0) {
1305         // task already started, pretend write completed and wait
1306         rb_state.written = rb_state.end;
1307         while(rb_state.stage != RB_STAGE_DONE) {
1308             msleep(10);
1309         }
1310         return 0;
1311     }
1312 
1313     // ensure thumbnail is written to uncached
1314     dcache_clean_all();
1315     write(fd, ADR_TO_UNCACHED(dng_header_buf), dng_header_buf_size + DNG_TH_BYTES);
1316     free_dng_header();
1317 
1318     while(rb_state.written < rb_state.end) {
1319         int size = rb_state.reversed - rb_state.written; 
1320         if(!size) {
1321             msleep(10);
1322             continue;
1323         }
1324         // if de-reversing, force DNG_NUM_END_CHUNKS at the end, gives better performance on vxworks
1325         // doesn't seem to have significant cost on dryos
1326         if(rawadr == altrawadr) {
1327             if(size > DNG_END_CHUNK_SIZE && (rb_state.written + DNG_END_CHUNK_SIZE*DNG_END_NUM_CHUNKS) >= rb_state.end) {
1328                 size = DNG_END_CHUNK_SIZE;
1329             }
1330         }
1331         // ensure reversed data is cleaned out to uncached before attempting write
1332         if(conf.raw_cache) {
1333             dcache_clean_all();
1334         }
1335         write(fd,ADR_TO_UNCACHED(rb_state.written),size);
1336         rb_state.written += size;
1337     }
1338 
1339     raw_closefile(fd);
1340 
1341     // wait for de-reverse, if required
1342     while(rb_state.stage != RB_STAGE_DONE) {
1343         msleep(10);
1344     }
1345     return 1;
1346 }
1347 
1348 void create_dng_header_for_ptp(ptp_data_chunk *pdc) 
1349 {
1350     create_dng_header(0,1);
1351     if (dng_header_buf) {
1352         pdc->address = (unsigned int)dng_header_buf; // cached may be slightly slower, but need to clean otherwise
1353         pdc->length = (unsigned int)dng_header_buf_size;
1354     } else {
1355         pdc->address = 0;
1356         pdc->length = 0;
1357     }
1358 }
1359 void free_dng_header_for_ptp()
1360 {
1361     free_dng_header();
1362 }
1363 
1364 /*********** BEGIN OF AUXILARY PART **********************/
1365 
1366 //---------------------------------------------------------
1367 // PURPOSE: Finalize module operations (close allocs, etc)
1368 // RETURN VALUE: 0-ok, 1-fail
1369 //---------------------------------------------------------
1370 int _module_unloader()
1371 {
1372     unload_bad_pixels_list_b();
1373     free_dng_header();
1374     return 0;
1375 }
1376 
1377 int _module_can_unload()
1378 {
1379     return (running == 0) && (remotecap_using_dng_module() == 0) && ((conf.save_raw == 0) || (conf.dng_raw == 0));
1380 }
1381 
1382 /******************** Module Information structure ******************/
1383 
1384 libdng_sym _libdng =
1385 {
1386     {
1387          0, _module_unloader, _module_can_unload, 0, 0
1388     },
1389 
1390     create_badpixel_bin,
1391     raw_init_badpixel_bin,
1392     capture_data_for_exif,
1393     load_bad_pixels_list_b,
1394     badpixel_list_loaded_b,
1395 
1396     convert_dng_to_chdk_raw,
1397     write_dng,
1398     load_dng_to_rawbuffer,
1399     // for remote capture
1400         create_dng_header_for_ptp,
1401         free_dng_header_for_ptp
1402 };
1403 
1404 ModuleInfo _module_info =
1405 {
1406     MODULEINFO_V1_MAGICNUM,
1407     sizeof(ModuleInfo),
1408     DNG_VERSION,                // Module version
1409 
1410     ANY_CHDK_BRANCH, 0, OPT_ARCHITECTURE,         // Requirements of CHDK version
1411     ANY_PLATFORM_ALLOWED,       // Specify platform dependency
1412 
1413     (int32_t)"DNG (dll)",
1414     MTYPE_EXTENSION,            //Processing of DNG
1415 
1416     &_libdng.base,
1417 
1418     CONF_VERSION,               // CONF version
1419     ANY_VERSION,                // CAM SCREEN version
1420     CAM_SENSOR_VERSION,         // CAM SENSOR version
1421     CAM_INFO_VERSION,           // CAM INFO version
1422 };
1423 
1424 /*************** END OF AUXILARY PART *******************/

/* [<][>][^][v][top][bottom][index][help] */