source: trunk/core/dng.c @ 1460

Revision 1460, 17.8 KB checked in by philmoz, 18 months ago (diff)

Fix for problem with camera name string in DNG files.
http://chdk.setepontos.com/index.php?topic=6341.msg77679#msg77679

  • Property svn:eol-style set to native
Line 
1#include "camera.h"
2
3#if DNG_SUPPORT
4
5#include "stdlib.h"
6#include "string.h"
7#include "platform.h"
8#include "math.h"
9#include "dng.h"
10
11const int cam_DefaultCropSize[]={CAM_JPEG_WIDTH, CAM_JPEG_HEIGHT};    // jpeg size
12const int cam_ActiveArea[]={CAM_ACTIVE_AREA_Y1, CAM_ACTIVE_AREA_X1, CAM_ACTIVE_AREA_Y2, CAM_ACTIVE_AREA_X2};
13const int cam_DefaultCropOrigin[]={CAM_DEFAULT_CROP_ORIGIN_W,CAM_DEFAULT_CROP_ORIGIN_H};
14#if defined(CAM_DNG_LENS_INFO)
15const int cam_lensinfo[] = CAM_DNG_LENS_INFO;
16#endif
17#if defined(CAM_DNG_EXPOSURE_BIAS)
18const int cam_BaselineExposure[]={CAM_DNG_EXPOSURE_BIAS};
19#else
20const int cam_BaselineExposure[]={-1,2};
21#endif
22const int cam_BaselineNoise[]={1,1};
23const int cam_BaselineSharpness[]={4,3};
24const int cam_LinearResponseLimit[]={1,1};
25const int cam_AnalogBalance[]={1,1,1,1,1,1};
26const int cam_ColorMatrix1[9*2]={CAM_COLORMATRIX1};
27const char cam_name[32];
28const short cam_PreviewBitsPerSample[]={8,8,8};
29const char cam_chdk_ver[]=HDK_VERSION" ver. "BUILD_NUMBER;
30const int cam_Resolution[]={180,1};
31int cam_AsShotNeutral[]={1000,1000,1000,1000,1000,1000};
32
33// warning: according to TIFF format specification, elements must be sorted by tag value in ascending order!
34
35struct dir_entry IFD0[]={
36 {0xFE,   T_LONG,      1,  1},       // NewSubFileType: Preview Image
37 {0x100,  T_LONG,      1,  DNG_TH_WIDTH},   // ImageWidth
38 {0x101,  T_LONG,      1,  DNG_TH_HEIGHT},   // ImageLength
39 {0x102,  T_SHORT,     3,  (int)cam_PreviewBitsPerSample},   // BitsPerSample: 8,8,8
40 {0x103,  T_SHORT,     1,  1},   // Compression: Uncompressed
41 {0x106,  T_SHORT,     1,  2}, //PhotometricInterpretation: RGB
42 {0x10E,  T_ASCII,     1,  0}, // ImageDescription
43 {0x10F,  T_ASCII,     sizeof(CAM_MAKE),  (int)CAM_MAKE}, // Make
44 {0x110,  T_ASCII,     32, (int)cam_name}, //Model: Filled at header generation.
45 {0x111,  T_LONG,      1,  0}, //StripOffsets: Offset
46 {0x112,  T_SHORT,     1,  1}, //Orientation: 1 - 0th row is top, 0th column is left
47 {0x115,  T_SHORT,     1,  3}, // SamplesPerPixel: 3
48 {0x116,  T_SHORT,     1,  DNG_TH_HEIGHT}, //RowsPerStrip
49 {0x117,  T_LONG,      1,  DNG_TH_WIDTH*DNG_TH_HEIGHT*3}, // StripByteCounts = preview size
50 {0x11C,  T_SHORT,     1,  1}, // PlanarConfiguration: 1
51 {0x131,  T_ASCII,     sizeof(cam_chdk_ver),  (int)cam_chdk_ver}, //Software
52 {0x132,  T_ASCII,     20, 0}, // DateTime
53 {0x14A,  T_LONG,      1,  0}, //SubIFDs offset
54 {0x8298, T_ASCII,     1,  0}, // Copyright
55 {0x8769, T_LONG,      1,  0}, //EXIF_IFD offset
56#if defined(OPT_GPS)
57 {0x8825, T_LONG,      1,  0}, //GPS_IFD offset
58#endif
59 {0x9216, T_BYTE,      4,  0x00000001},  // TIFF/EPStandardID: 1.0.0.0
60 {0xC612, T_BYTE,      4,  0x00000101}, //DNGVersion: 1.1.0.0
61 {0xC614, T_ASCII,     32, (int)cam_name}, //UniqueCameraModel. Filled at header generation.
62 {0xC621, T_SRATIONAL, 9,  (int)cam_ColorMatrix1},
63 {0xC627, T_RATIONAL,  3,  (int)cam_AnalogBalance},
64 {0xC628, T_RATIONAL,  3,  (int)cam_AsShotNeutral},
65 {0xC62A, T_SRATIONAL, 1,  (int)cam_BaselineExposure},
66 {0xC62B, T_RATIONAL,  1,  (int)cam_BaselineNoise},
67 {0xC62C, T_RATIONAL,  1,  (int)cam_BaselineSharpness},
68 {0xC62E, T_RATIONAL,  1,  (int)cam_LinearResponseLimit},
69#if defined(CAM_DNG_LENS_INFO)
70 {0xC630, T_RATIONAL,  4,  (int)cam_lensinfo},
71#endif
72 {0xC65A, T_SHORT,     1,  cam_CalibrationIlluminant1},
73 {0}
74};
75
76                                                                                     
77struct dir_entry IFD1[]={
78 {0xFE,   T_LONG,      1,  0},       // NewSubFileType: Main Image
79 {0x100,  T_LONG,      1,  CAM_RAW_ROWPIX},   // ImageWidth
80 {0x101,  T_LONG,      1,  CAM_RAW_ROWS},   // ImageLength
81 {0x102,  T_SHORT,     1,  CAM_SENSOR_BITS_PER_PIXEL},   // BitsPerSample
82 {0x103,  T_SHORT,     1,  1},   // Compression: Uncompressed
83 {0x106,  T_SHORT,     1,  0x8023}, //PhotometricInterpretation: CFA
84 {0x111,  T_LONG,      1,  0}, //StripOffsets: Offset
85 {0x115,  T_SHORT,     1,  1}, // SamplesPerPixel: 1
86 {0x116,  T_SHORT,     1,  CAM_RAW_ROWS}, //RowsPerStrip
87 {0x117,  T_LONG,      1,  CAM_RAW_ROWPIX*CAM_RAW_ROWS*CAM_SENSOR_BITS_PER_PIXEL/8}, // StripByteCounts = CHDK RAW size
88 {0x11A,  T_RATIONAL,  1,  (int)cam_Resolution}, // XResolution
89 {0x11B,  T_RATIONAL,  1,  (int)cam_Resolution}, // YResolution
90 {0x11C,  T_SHORT,     1,  1}, // PlanarConfiguration: 1
91 {0x128,  T_SHORT,     1,  2}, // ResolutionUnit: inch
92 {0x828D, T_SHORT,     2,  0x00020002}, // CFARepeatPatternDim: Rows = 2, Cols = 2
93 {0x828E, T_BYTE,      4,  cam_CFAPattern},
94 {0xC61A, T_LONG,      1,  CAM_BLACK_LEVEL}, // BlackLevel
95 {0xC61D, T_LONG,      1,  CAM_WHITE_LEVEL}, // WhiteLevel
96 {0xC61F, T_LONG,      2,  (int)cam_DefaultCropOrigin},
97 {0xC620, T_LONG,      2,  (int)cam_DefaultCropSize},
98 {0xC68D, T_LONG,      4,  (int)cam_ActiveArea},
99 {0}
100};
101
102
103struct dir_entry EXIF_IFD[]={
104 {0x829A, T_RATIONAL,  1,  0}, //ExposureTime
105 {0x829D, T_RATIONAL,  1,  0}, //FNumber
106 {0x8822, T_SHORT,     1,  0}, //ExposureProgram
107 {0x8827, T_SHORT,     1,  0}, //ISOSpeedRatings
108 {0x9000, T_UNDEFINED, 4,  0x31323230}, // ExifVersion: 2.21
109 {0x9003, T_ASCII,     20, 0}, // DateTimeOriginal
110 {0x9201, T_SRATIONAL, 1,  0}, // ShutterSpeedValue
111 {0x9202, T_RATIONAL,  1,  0}, // ApertureValue
112 {0x9204, T_SRATIONAL, 1,  0}, // ExposureBias
113 {0x9205, T_RATIONAL,  1,  0}, //MaxApertureValue
114 {0x9207, T_SHORT,     1,  0}, // Metering mode
115 {0x9209, T_SHORT,     1,  0}, // Flash mode
116 {0x920A, T_RATIONAL,  1,  0}, //FocalLength
117 {0xA405, T_SHORT,     1,  0}, //FocalLengthIn35mmFilm
118 {0}
119};
120
121
122#if defined(OPT_GPS)
123struct dir_entry GPS_IFD[]={
124// {0x0000, T_BYTE,      4,  0x00000302}, //GPSVersionID: 2 3 0 0
125 {0x0001, T_ASCII,     2,  0}, //North or South Latitude "N\0" or "S\0"
126 {0x0002, T_RATIONAL,  3,  0}, //Latitude
127 {0x0003, T_ASCII,     2,  0}, //East or West Latitude "E\0" or "W\0"
128 {0x0004, T_RATIONAL,  3,  0}, //Longitude
129 {0x0005, T_ASCII,     2,  0}, //AltitudeRef
130 {0x0006, T_RATIONAL,  3,  0}, //Altitude
131 {0x0007, T_RATIONAL,  3,  0}, //TimeStamp
132 {0x0009, T_ASCII,     2,  0}, //Status
133// {0x000A, T_ASCII,     1,  0}, //MeasureMode
134 {0x0012, T_ASCII,     8,  0}, //MapDatum 7 + 1 pad byte
135 {0x001D, T_ASCII,    12,  0}, //DateStamp 11 + 1 pad byte
136 {0}
137};
138#endif
139
140
141int get_type_size(int type){
142 switch(type){
143  case T_BYTE:      return 1;
144  case T_ASCII:     return 1;
145  case T_SHORT:     return 2;
146  case T_LONG:      return 4;
147  case T_RATIONAL:  return 8;
148  case T_SBYTE:     return 1;
149  case T_UNDEFINED: return 1;
150  case T_SSHORT:    return 2;
151  case T_SLONG:     return 4;
152  case T_SRATIONAL: return 8;
153  case T_FLOAT:     return 4;
154  case T_DOUBLE:    return 8;
155  default: return 0;
156 }
157}
158
159#if defined(OPT_GPS)
160struct {struct dir_entry* entry; int count;} IFD_LIST[]={{IFD0,0}, {IFD1,0}, {EXIF_IFD,0}, {GPS_IFD, 0}};
161#else
162struct {struct dir_entry* entry; int count;} IFD_LIST[]={{IFD0,0}, {IFD1,0}, {EXIF_IFD,0}};
163#endif
164
165#define IFDs (sizeof(IFD_LIST)/sizeof(IFD_LIST[0]))
166
167#define TIFF_HDR_SIZE (8)
168
169char* tmp_buf;
170int tmp_buf_size;
171int tmp_buf_offset;
172void add_to_buf(void* var, int size){
173 memcpy(tmp_buf+tmp_buf_offset,var,size);
174 tmp_buf_offset+=size;
175}
176 
177void create_dng_header(struct t_data_for_exif* exif_data){
178 int var;
179 int i,j;
180 int extra_offset;
181 int raw_offset;
182
183 // filling EXIF fields
184 
185#if defined(OPT_GPS)
186typedef struct {
187    int latitudeRef;
188    int latitude[6];
189    int longitudeRef;
190    int longitude[6];
191    int heightRef;
192    int height[2];
193    int timeStamp[6];
194    short status;
195    char mapDatum[7];
196    char dateStamp[11];
197    char unknown2[260];
198} tGPS;
199tGPS gps;
200
201get_property_case(PROPCASE_GPS, &gps, sizeof(tGPS));
202#endif
203
204 for (j=0;j<IFDs;j++) {
205  for(i=0; IFD_LIST[j].entry[i].tag; i++) {
206    switch (IFD_LIST[j].entry[i].tag) {
207         // For camera name string make sure the 'count' in the IFD header is correct for the string
208     case 0x110 :                                                                                       // CameraName
209     case 0xC614: IFD_LIST[j].entry[i].count = strlen((char*)IFD_LIST[j].entry[i].offset) + 1; break;   // UniqueCameraModel
210     case 0x132 :
211     case 0x9003: IFD_LIST[j].entry[i].offset=(int)get_date_for_exif(exif_data->time); break; //DateTimeOriginal
212     case 0x8827: IFD_LIST[j].entry[i].offset=exif_data->iso; break;//ISOSpeedRatings
213     case 0x829D: IFD_LIST[j].entry[i].offset=(int)get_av_for_exif(exif_data->av); break; //FNumber
214     case 0x829A: IFD_LIST[j].entry[i].offset=(int)get_tv_for_exif(exif_data->tv); break; //ExposureTime
215     case 0x9205: IFD_LIST[j].entry[i].offset=(int)get_max_av_for_exif(exif_data->max_av); break; //MaxApertureValue
216     case 0x9204: IFD_LIST[j].entry[i].offset=(int)get_exp_bias_for_exif(exif_data->exp_bias); break; //ExposureBias
217     case 0x8822: IFD_LIST[j].entry[i].offset=get_exp_program_for_exif(exif_data->exp_program); break;//ExposureProgram
218     case 0x920A: IFD_LIST[j].entry[i].offset=(int)get_focal_length_for_exif(exif_data->focal_length); break; //FocalLength
219     case 0xA405: IFD_LIST[j].entry[i].offset=exif_data->effective_focal_length/1000; break; ////FocalLengthIn35mmFilm
220     case 0x0112: IFD_LIST[j].entry[i].offset=get_orientation_for_exif(exif_data->orientation); break; //Orientation
221     case 0x9209: IFD_LIST[j].entry[i].offset=get_flash_mode_for_exif(exif_data->flash_mode, exif_data->flash_fired); break; //Flash mode
222     case 0x9207: IFD_LIST[j].entry[i].offset=get_metering_mode_for_exif(exif_data->metering_mode); break; // Metering mode
223     case 0x9201: IFD_LIST[j].entry[i].offset=(int)get_shutter_speed_for_exif(exif_data->tv); break; // ShutterSpeedValue
224     case 0x9202: IFD_LIST[j].entry[i].offset=(int)get_aperture_for_exif(exif_data->av); break; // ApertureValue
225#if defined(OPT_GPS)
226     case 0x0001: IFD_LIST[j].entry[i].offset=gps.latitudeRef; break;
227     case 0x0002: IFD_LIST[j].entry[i].offset=(int)&(gps.latitude); break;
228     case 0x0003: IFD_LIST[j].entry[i].offset=gps.longitudeRef; break;
229     case 0x0004: IFD_LIST[j].entry[i].offset=(int)&(gps.longitude); break;
230     case 0x0005: IFD_LIST[j].entry[i].offset=gps.heightRef; break;
231     case 0x0006: IFD_LIST[j].entry[i].offset=(int)&(gps.height); break;
232     case 0x0007: IFD_LIST[j].entry[i].offset=(int)&(gps.timeStamp); break;
233     case 0x0009: IFD_LIST[j].entry[i].offset=(int)gps.status; break;
234     case 0x0012: IFD_LIST[j].entry[i].offset=(int)&(gps.mapDatum); break;
235     case 0x001D: IFD_LIST[j].entry[i].offset=(int)&(gps.dateStamp); break;
236#endif
237    }
238  }
239 }
240 
241 // calculating offset of RAW data and count of directories for each IFD
242
243 raw_offset=TIFF_HDR_SIZE;
244
245 for (j=0;j<IFDs;j++) {
246  IFD_LIST[j].count=0;
247  raw_offset+=6; // IFD header+footer
248  for(i=0; IFD_LIST[j].entry[i].tag; i++) {
249   int size_ext;
250   IFD_LIST[j].count++;
251   raw_offset+=12; // IFD directory size
252   size_ext=get_type_size(IFD_LIST[j].entry[i].type)*IFD_LIST[j].entry[i].count;
253   if (size_ext>4) raw_offset+=size_ext+(size_ext&1);
254  }
255 }
256
257 // creating buffer for writing data
258 raw_offset=(raw_offset/512+1)*512; // exlusively for CHDK fast file writing
259 tmp_buf_size=raw_offset;
260 tmp_buf=umalloc(raw_offset);
261 tmp_buf_offset=0;
262 if (!tmp_buf) return;
263
264 //  writing  offsets for EXIF IFD and RAW data and calculating offset for extra data
265
266 extra_offset=TIFF_HDR_SIZE;
267
268 for (j=0;j<IFDs;j++) {
269  extra_offset+=6+IFD_LIST[j].count*12; // IFD header+footer
270  for(i=0; IFD_LIST[j].entry[i].tag; i++) {
271   if (IFD_LIST[j].entry[i].tag==0x8769) IFD_LIST[j].entry[i].offset=TIFF_HDR_SIZE+(IFD_LIST[0].count+IFD_LIST[1].count)*12+6+6;  // EXIF IFD offset
272#if defined(OPT_GPS)
273   if (IFD_LIST[j].entry[i].tag==0x8825) IFD_LIST[j].entry[i].offset=TIFF_HDR_SIZE+(IFD_LIST[0].count+IFD_LIST[1].count+IFD_LIST[2].count)*12+6+6+6;  // GPS IFD offset
274#endif
275   if (IFD_LIST[j].entry[i].tag==0x14A)  IFD_LIST[j].entry[i].offset=TIFF_HDR_SIZE+IFD_LIST[0].count*12+6; // SubIFDs offset
276   if (IFD_LIST[j].entry[i].tag==0x111)  {
277    if (j==1) IFD_LIST[j].entry[i].offset=raw_offset+DNG_TH_WIDTH*DNG_TH_HEIGHT*3;  //StripOffsets for main image
278    if (j==0) IFD_LIST[j].entry[i].offset=raw_offset;  //StripOffsets for thumbnail
279   }
280  }
281 }
282
283 // TIFF file header
284
285 var=0x4949; // little endian
286 add_to_buf(&var, sizeof(short));
287 var=42; //An arbitrary but carefully chosen number that further identifies the file as a TIFF file.
288 add_to_buf(&var, sizeof(short));
289 var=0x8; // offset of first IFD
290 add_to_buf(&var, sizeof(int));
291
292
293 // writing IFDs
294
295 for (j=0;j<IFDs;j++) {
296  int size_ext;
297  var=IFD_LIST[j].count;
298  add_to_buf(&var, sizeof(short));
299  for(i=0; IFD_LIST[j].entry[i].tag; i++) {
300   add_to_buf(&IFD_LIST[j].entry[i].tag, sizeof(short));
301   add_to_buf(&IFD_LIST[j].entry[i].type, sizeof(short));
302   add_to_buf(&IFD_LIST[j].entry[i].count, sizeof(int));
303   size_ext=get_type_size(IFD_LIST[j].entry[i].type)*IFD_LIST[j].entry[i].count;
304   if (size_ext<=4) add_to_buf(&IFD_LIST[j].entry[i].offset, sizeof(int));
305   else {
306    add_to_buf(&extra_offset, sizeof(int));
307    extra_offset+=size_ext+(size_ext&1);   
308   }
309  }
310 var=0;
311 add_to_buf(&var, sizeof(int));
312 }
313
314
315 // writing extra data
316
317 for (j=0;j<IFDs;j++) {
318  int size_ext;
319  char zero=0;
320  for(i=0; IFD_LIST[j].entry[i].tag; i++) {
321   size_ext=get_type_size(IFD_LIST[j].entry[i].type)*IFD_LIST[j].entry[i].count;
322   if (size_ext>4){
323    add_to_buf((void*)IFD_LIST[j].entry[i].offset, size_ext);
324    if (size_ext&1) add_to_buf(&zero, 1);
325   }
326  }
327 }
328
329
330 // writing zeros to tail of dng header (just for fun)
331 for (i=tmp_buf_offset; i<tmp_buf_size; i++) tmp_buf[i]=0;
332
333}
334
335void free_dng_header(void){
336 ufree(tmp_buf);
337 tmp_buf=NULL;
338}
339
340char* get_dng_header(void){
341 return tmp_buf;
342}
343
344int get_dng_header_size(void){
345 return tmp_buf_size;
346}
347
348char *get_date_for_exif(unsigned long time){
349 static char buf[20];
350 struct tm *ttm;
351 ttm = localtime(&time);
352 sprintf(buf, "%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);
353 return buf;
354}
355
356unsigned int* get_av_for_exif(short av){
357 static unsigned int fnumber[2]={0,10};
358 fnumber[0]=10*pow(2,av/192.0);
359 return fnumber;
360}
361
362int* get_tv_for_exif(short tv){
363 static int exp_time[2]={0,1000000};
364 exp_time[0]=1000000*pow(2,-tv/96.0);
365 return exp_time;
366}
367
368unsigned int* get_max_av_for_exif(short max_av){
369 static unsigned int mav[2]={0,96};
370 mav[0]=max_av;
371 return mav;
372}
373
374int* get_exp_bias_for_exif(short exp_bias){
375 static int bias[2]={0,96};
376 bias[0]=exp_bias;
377 return bias;
378}
379
380int* get_shutter_speed_for_exif(short tv){
381 static int speed[2]={0,96};
382 speed[0]=tv;
383 return speed;
384}
385
386int* get_aperture_for_exif(short av){
387 static int aperture[2]={0,96};
388 aperture[0]=av;
389 return aperture;
390}
391
392
393unsigned short get_exp_program_for_exif(int exp_program){
394 switch(exp_program){
395  case MODE_M: return 1;
396  case MODE_P: return 2;
397  case MODE_AV: return 3;
398  case MODE_TV: return 4;
399  default: return 0;
400 }
401}
402
403unsigned int* get_focal_length_for_exif(int focal_length){
404 static unsigned int fl[2]={0,1000};
405 fl[0]=focal_length;
406 return fl;
407}
408
409unsigned short get_orientation_for_exif(short orientation){
410 switch(orientation){
411  case  90: return 6;  // Right  - Top
412  case 180: return 3;  // Bottom - Right
413  case 270: return 8;  // Left   - Bottom
414  case   0:            // Top    - Left
415  default : return 1;
416 }
417}
418
419unsigned short get_flash_mode_for_exif(short mode, short fired){
420 fired&=1;
421 switch(mode){
422  case 0: return (3<<3)|fired; // auto
423  case 1: return (1<<3)|fired; // on
424  case 2: return (2<<3)|fired; // off
425  default: return fired;
426 };
427}
428
429unsigned short get_metering_mode_for_exif(short metering_mode){
430 switch (metering_mode){
431  case 0: return 5; // Evaluative
432  case 1: return 3; // Spot
433  case 2: return 2; // CenterWeightedAverage
434  default: return 255; // other
435 }
436}
437
438struct t_data_for_exif* capture_data_for_exif(void){
439 static struct t_data_for_exif data;
440 extern volatile long shutter_open_time; // defined in platform/generic/capt_seq.c
441 int wb[3];
442 data.iso=shooting_get_iso_market();
443 get_property_case(PROPCASE_TV, &data.tv, sizeof(data.tv));
444 if (shutter_open_time) { data.time=shutter_open_time+pow(2,-data.tv/96.0); shutter_open_time=0;} // shutter closing time
445 else  data.time=time(NULL);
446 get_property_case(PROPCASE_AV, &data.av, sizeof(data.av));
447 get_property_case(PROPCASE_MIN_AV, &data.max_av, sizeof(data.max_av));
448 get_property_case(PROPCASE_EV_CORRECTION_2, &data.exp_bias, sizeof(data.exp_bias));
449 data.exp_program=mode_get() & MODE_SHOOTING_MASK;
450 data.focal_length=get_focal_length(shooting_get_zoom());
451 data.effective_focal_length=get_effective_focal_length(shooting_get_zoom());
452 get_property_case(PROPCASE_ORIENTATION_SENSOR, &data.orientation, sizeof(data.orientation));
453 get_parameter_data(PARAM_CAMERA_NAME, &cam_name, sizeof(cam_name));
454 get_property_case(PROPCASE_FLASH_MODE, &data.flash_mode, sizeof(data.flash_mode));
455 get_property_case(PROPCASE_FLASH_FIRE, &data.flash_fired, sizeof(data.flash_fired));
456 get_property_case(PROPCASE_METERING_MODE, &data.metering_mode, sizeof(data.metering_mode));
457 get_property_case(PROPCASE_WB_ADJ, &wb, sizeof(wb)); 
458 cam_AsShotNeutral[1]=wb[1];
459 cam_AsShotNeutral[3]=wb[0];
460 cam_AsShotNeutral[5]=wb[2];
461 return &data;
462}
463
464void convert_dng_to_chdk_raw(char* fn){
465 #define BUF_SIZE (32768)
466 FILE *dng, *raw;
467 int *buf;
468 int i;
469 struct stat st;
470 struct utimbuf t;
471
472 if (stat(fn, &st) != 0 || st.st_size<=hook_raw_size())  return;
473 buf=malloc(BUF_SIZE);
474 if (buf){
475  started();
476  dng=fopen(fn,"rb");
477  if (dng){
478   fread(buf, 1, 8, dng);
479   if (buf[0]==0x2A4949 && buf[1]==8) {  // chdk dng header
480    i=strlen(fn)-3;
481    if (strncmp(fn+i,"CR",2)==0) strcpy(fn+i,"WAV"); else strcpy(fn+i,"CRW");
482    raw=fopen(fn,"w+b");
483    if (raw){
484     fseek(dng, st.st_size-hook_raw_size(), SEEK_SET); // SEEK_END is not working?
485     for (i=0; i<hook_raw_size()/BUF_SIZE; i++) {
486      fread(buf, 1, BUF_SIZE, dng);
487      reverse_bytes_order((char*)buf, BUF_SIZE);
488      fwrite(buf, 1, BUF_SIZE, raw);
489     }
490     fread(buf, 1, hook_raw_size()%BUF_SIZE, dng);
491     reverse_bytes_order((char*)buf, hook_raw_size()%BUF_SIZE);
492     fwrite(buf, 1, hook_raw_size()%BUF_SIZE, raw);
493     fclose(raw);
494     t.actime = t.modtime = time(NULL);
495     utime(fn, &t);
496    } // if (raw)
497   } // if chdk dng header
498  fclose(dng);
499  } //if (dng)
500 free(buf);
501 finished();
502 }  //if (buf)
503}
504
505#endif //DNG_SUPPORT
Note: See TracBrowser for help on using the repository browser.