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

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