source: trunk/core/raw.c @ 623

Revision 623, 11.7 KB checked in by EWAVR, 4 years ago (diff)

+added optional DNG extension for DNG files
+added possibility to create badpixel.bin from scripts
-fixed small bug in file browser - http://chdk.kernreaktor.org/mantis/view.php?id=129

  • Property svn:eol-style set to native
Line 
1#include "platform.h"
2#include "conf.h"
3#include "stdlib.h"
4#include "raw.h"
5#if DNG_SUPPORT
6        #include "dng.h"
7        #include "math.h"
8#endif
9#ifdef OPT_CURVES
10        #include "curves.h"
11#endif
12#include "shot_histogram.h"
13
14//-------------------------------------------------------------------
15#define RAW_TARGET_DIRECTORY    "A/DCIM/%03dCANON"
16//#define RAW_TMP_FILENAME        "HDK_RAW.TMP"
17#define RAW_TARGET_FILENAME     "%s%04d%s"
18#define RAW_BRACKETING_FILENAME "%s%04d_%02d%s"
19
20//-------------------------------------------------------------------
21static char fn[64];
22static char dir[32];
23static int develop_raw=0;
24//-------------------------------------------------------------------
25void raw_prepare_develop(const char* filename){
26 if (filename) {
27  develop_raw=1;
28  strcpy(fn,filename);
29 }
30 else {
31  develop_raw=0;
32 }
33}
34
35//-------------------------------------------------------------------
36void patch_bad_pixels(void);
37//-------------------------------------------------------------------
38
39char* get_raw_image_addr(void){
40 if (!conf.raw_cache) return hook_raw_image_addr();
41 else return (char*) ((int)hook_raw_image_addr()&~0x10000000);
42}
43
44//-------------------------------------------------------------------
45
46unsigned int get_bad_count_and_write_file(char *fn){
47 int count=0;
48 unsigned short c[2];
49 FILE*f;
50 f=fopen(fn,"w+b");
51 for (c[1]=0; c[1]<CAM_RAW_ROWS; c[1]++)
52   for (c[0]=0; c[0]<CAM_RAW_ROWPIX; c[0]++)
53    if (get_raw_pixel(c[0],c[1])==0) { fwrite(c, 1, 4, f); count++;}
54 fclose(f);
55 return count;
56}
57
58
59//-------------------------------------------------------------------
60#if DNG_SUPPORT
61unsigned short get_raw_pixel(unsigned int x,unsigned  int y);
62
63static unsigned char gamma[256];
64
65void fill_gamma_buf(void){
66 int i;
67 if (gamma[255]) return;
68 for (i=0; i<=255; i++) gamma[i]=255*pow(i/255.0, 0.5);
69}
70
71
72void create_thumbnail(char* buf){
73 unsigned int i, j, x, y;
74 unsigned char r, g, b;
75 for (i=0; i<DNG_TH_HEIGHT; i++)
76   for (j=0; j<DNG_TH_WIDTH; j++) {
77    x=CAM_ACTIVE_AREA_X1+((CAM_ACTIVE_AREA_X2-CAM_ACTIVE_AREA_X1)*j)/DNG_TH_WIDTH;
78    y=CAM_ACTIVE_AREA_Y1+((CAM_ACTIVE_AREA_Y2-CAM_ACTIVE_AREA_Y1)*i)/DNG_TH_HEIGHT;
79#if cam_CFAPattern==0x02010100    // Red  Green  Green  Blue
80    r=gamma[get_raw_pixel((x/2)*2,(y/2)*2)>>2]; // red pixel
81    g=gamma[6*(get_raw_pixel((x/2)*2+1,(y/2)*2)>>2)/10]; // green pixel
82    b=gamma[get_raw_pixel((x/2)*2+1,(y/2)*2+1)>>2]; //blue pixel
83#elif cam_CFAPattern==0x01000201 // Green  Blue  Red  Green
84    r=gamma[get_raw_pixel((x/2)*2,(y/2)*2+1)>>2]; // red pixel
85    g=gamma[6*(get_raw_pixel((x/2)*2,(y/2)*2)>>2)/10]; // green pixel
86    b=gamma[get_raw_pixel((x/2)*2+1,(y/2)*2)>>2]; //blue pixel
87#else
88 #error please define new pattern here
89#endif
90    *buf++=r; *buf++=g; *buf++=b;
91   }
92}
93#endif
94//-------------------------------------------------------------------
95
96int raw_savefile() {
97                int fd, m=(mode_get()&MODE_SHOOTING_MASK);
98    static struct utimbuf t;
99    static int br_counter;
100#if DNG_SUPPORT
101     struct t_data_for_exif* exif_data = NULL; 
102     char *thumbnail_buf = NULL;
103     if (conf.dng_raw) exif_data=capture_data_for_exif();
104#endif   
105    if (state_kbd_script_run && shot_histogram_enabled) build_shot_histogram();
106
107    // ! ! ! exclusively for special script which creates badpixel.bin ! ! !
108    if (conf.save_raw==255) conf.save_raw=get_bad_count_and_write_file("A/CHDK/bad_tmp.bin");
109    //
110
111    if (develop_raw) {
112     started();
113     fd = open(fn, O_RDONLY, 0777);
114     if (fd>=0) {
115      read(fd, get_raw_image_addr(), hook_raw_size());
116      close(fd);
117      }
118#ifdef OPT_CURVES
119     if (conf.curve_enable) curve_apply();
120#endif
121     finished();
122     develop_raw=0;
123     return 0;
124    }
125
126    if (conf.bad_pixel_removal) patch_bad_pixels();
127
128    shooting_bracketing();
129
130    if(conf.tv_bracket_value || conf.av_bracket_value || conf.iso_bracket_value || conf.subj_dist_bracket_value) {
131        if(state_shooting_progress != SHOOTING_PROGRESS_PROCESSING)
132            br_counter = 1;
133        else
134            br_counter++;
135    }
136    else
137        br_counter=0;
138
139
140    // got here second time in a row. Skip second RAW saving.
141    if (conf.raw_save_first_only && state_shooting_progress == SHOOTING_PROGRESS_PROCESSING) {
142        return 0;
143    }
144   
145    state_shooting_progress = SHOOTING_PROGRESS_PROCESSING;
146
147     if (conf.save_raw && (!((movie_status > 1) && conf.save_raw_in_video   )) && (!((m==MODE_SPORTS) && conf.save_raw_in_sports)) && (!((m==MODE_AUTO) && conf.save_raw_in_auto)) && (!(conf.edge_overlay_enable && conf.save_raw_in_edgeoverlay)) && (!((shooting_get_prop(PROPCASE_DRIVE_MODE)==1) && conf.save_raw_in_burst && !(m==MODE_SPORTS))) && (!((shooting_get_prop(PROPCASE_DRIVE_MODE)>=2) && conf.save_raw_in_timer)) && (!((shooting_get_prop(PROPCASE_BRACKET_MODE)==1) && conf.save_raw_in_ev_bracketing)) ) {
148        long v;
149int timer; char txt[30];
150
151        started();
152
153        t.actime = t.modtime = time(NULL);
154
155        mkdir("A/DCIM");
156        sprintf(dir, RAW_TARGET_DIRECTORY, (conf.raw_in_dir)?get_target_dir_num():100);
157        mkdir(dir);
158
159        sprintf(fn, "%s/", dir);
160        if(br_counter && conf.bracketing_add_raw_suffix && (shooting_get_prop(PROPCASE_DRIVE_MODE)!=0))
161            sprintf(fn+strlen(fn), RAW_BRACKETING_FILENAME, img_prefixes[conf.raw_prefix], get_target_file_num(), br_counter, img_exts[conf.raw_ext]);
162        else
163            sprintf(fn+strlen(fn), RAW_TARGET_FILENAME, img_prefixes[conf.raw_prefix], get_target_file_num(),
164              conf.dng_raw&&conf.raw_dng_ext ? ".DNG" : img_exts[conf.raw_ext]);
165        fd = open(fn, O_WRONLY|O_CREAT, 0777);
166        if (fd>=0) {
167timer=get_tick_count();
168#if DNG_SUPPORT
169            if (conf.dng_raw) {
170             fill_gamma_buf();
171             create_dng_header(exif_data);
172             thumbnail_buf = malloc(DNG_TH_WIDTH*DNG_TH_HEIGHT*3);
173              if (get_dng_header() && thumbnail_buf) {
174               patch_bad_pixels_b();
175               create_thumbnail(thumbnail_buf);
176               write(fd, get_dng_header(), get_dng_header_size());
177               write(fd, thumbnail_buf, DNG_TH_WIDTH*DNG_TH_HEIGHT*3);
178               reverse_bytes_order(get_raw_image_addr(), hook_raw_size());
179             }
180            }
181#endif
182            write(fd, get_raw_image_addr(), hook_raw_size());
183            close(fd);
184            utime(fn, &t);
185#if DNG_SUPPORT
186            if (conf.dng_raw) {
187             if (get_dng_header() && thumbnail_buf) {
188              reverse_bytes_order(get_raw_image_addr(), hook_raw_size());
189          //   unpatch_bad_pixels_b();
190              }
191             if (get_dng_header()) free_dng_header();
192             if (thumbnail_buf) free(thumbnail_buf);
193            }
194#endif
195if (conf.raw_timer)
196        {
197    timer=get_tick_count()-timer;
198    sprintf(txt, "saving time=%d", timer);
199    script_console_add_line(txt);
200  }
201        }
202
203        finished();
204
205        return (fd >= 0);
206    }
207
208#ifdef OPT_CURVES
209    if (conf.curve_enable) curve_apply();
210#endif
211    return 0;
212}
213
214//-------------------------------------------------------------------
215void raw_postprocess() {
216}
217
218//-------------------------------------------------------------------
219
220void set_raw_pixel(unsigned int x, unsigned int y, unsigned short value){
221 unsigned char* addr=get_raw_image_addr()+y*RAW_ROWLEN+(x/8)*10;
222 switch (x%8) {
223  case 0: addr[0]=(addr[0]&0x3F)|(value<<6); addr[1]=value>>2;                  break;
224  case 1: addr[0]=(addr[0]&0xC0)|(value>>4); addr[3]=(addr[3]&0x0F)|(value<<4); break;
225  case 2: addr[2]=(addr[2]&0x03)|(value<<2); addr[3]=(addr[3]&0xF0)|(value>>6); break;
226  case 3: addr[2]=(addr[2]&0xFC)|(value>>8); addr[5]=value;                     break;
227  case 4: addr[4]=value>>2;                  addr[7]=(addr[7]&0x3F)|(value<<6); break;
228  case 5: addr[6]=(addr[6]&0x0F)|(value<<4); addr[7]=(addr[7]&0xC0)|(value>>4); break;
229  case 6: addr[6]=(addr[6]&0xF0)|(value>>6); addr[9]=(addr[9]&0x03)|(value<<2); break;
230  case 7: addr[8]=value;                     addr[9]=(addr[9]&0xFC)|(value>>8); break;
231 }
232}
233
234//-------------------------------------------------------------------
235unsigned short get_raw_pixel(unsigned int x,unsigned  int y){
236 unsigned char* addr=get_raw_image_addr()+y*RAW_ROWLEN+(x/8)*10;
237 switch (x%8) {
238  case 0: return ((0x3fc&(((unsigned short)addr[1])<<2)) | (addr[0] >> 6));
239  case 1: return ((0x3f0&(((unsigned short)addr[0])<<4)) | (addr[3] >> 4));
240  case 2: return ((0x3c0&(((unsigned short)addr[3])<<6)) | (addr[2] >> 2));
241  case 3: return ((0x300&(((unsigned short)addr[2])<<8)) | (addr[5]));
242  case 4: return ((0x3fc&(((unsigned short)addr[4])<<2)) | (addr[7] >> 6));
243  case 5: return ((0x3f0&(((unsigned short)addr[7])<<4)) | (addr[6] >> 4));
244  case 6: return ((0x3c0&(((unsigned short)addr[6])<<6)) | (addr[9] >> 2));
245  case 7: return ((0x300&(((unsigned short)addr[9])<<8)) | (addr[8]));
246 }
247 return 0;
248}
249
250//-------------------------------------------------------------------
251void patch_bad_pixel(unsigned int x,unsigned  int y){
252 int sum=0;
253 int nzero=0;
254 int i,j;
255 int val;
256 if ((x>=2) && (x<CAM_RAW_ROWPIX-2) && (y>=2) && (y<CAM_RAW_ROWS-2)) {
257  if ((conf.bad_pixel_removal==1) || conf.dng_raw) {  // interpolation or DNG saving
258   for (i=-2; i<=2; i+=2)
259    for (j=-2; j<=2; j+=2)
260     if ((i!=0) && (j!=0)) {
261      val=get_raw_pixel(x+i, y+j);
262      if (val) {sum+=val; nzero++;}
263     }
264   if (nzero) set_raw_pixel(x,y,sum/nzero);
265  }
266  else if (conf.bad_pixel_removal==2)  // or this makes RAW converter (internal/external)
267   set_raw_pixel(x,y,0);   
268 }
269}
270
271struct point{
272 int x;
273 int y;
274 struct point *next;
275} *pixel_list=NULL;
276
277void patch_bad_pixels(void){
278 struct point *pixel=pixel_list;
279 while (pixel){
280  patch_bad_pixel((*pixel).x,(*pixel).y);
281  pixel=(*pixel).next;
282 }
283}
284
285void make_pixel_list(char * ptr){
286 int x,y;
287 struct point *pixel;
288 char *endptr;
289 while(*ptr){
290  while (*ptr==' ' || *ptr=='\t') ++ptr; // whitespaces
291   x=strtol(ptr, &endptr, 0);
292   if (endptr != ptr) {
293    ptr = endptr;
294    if (*ptr++==',') {
295     while (*ptr==' ' || *ptr=='\t') ++ptr; // whitespaces
296     if (*ptr!='\n' && *ptr!='\r'){
297      y=strtol(ptr, &endptr, 0);
298      if (endptr != ptr) {
299       ptr = endptr;
300       pixel=malloc(sizeof(struct point));
301       if (pixel) {
302        (*pixel).x=x;
303        (*pixel).y=y;
304        (*pixel).next=pixel_list;
305        pixel_list=pixel;
306       }
307      }
308     }
309    }
310   }
311   while (*ptr && *ptr!='\n') ++ptr; // unless end of line
312   if (*ptr) ++ptr;
313 }
314}
315
316#define PIXELS_BUF_SIZE 8192
317void load_bad_pixels_list(const char* filename){
318    char *buf;
319    int fd;
320
321    if (filename) {
322        buf = umalloc(PIXELS_BUF_SIZE);
323        if (!buf) return;
324
325        fd = open(filename, O_RDONLY, 0777);
326        if (fd>=0) {
327            int rcnt = read(fd, buf, PIXELS_BUF_SIZE);
328            if (rcnt > 0) {
329                if (rcnt == PIXELS_BUF_SIZE)
330                    buf[PIXELS_BUF_SIZE-1] = 0;
331                else
332                    buf[rcnt] = 0;
333            }
334            close(fd);
335        }
336        make_pixel_list(buf);   
337        ufree(buf);
338    }
339
340}
341
342#if DNG_SUPPORT
343short* binary_list=NULL;
344int binary_count=0;
345
346void load_bad_pixels_list_b(char* filename){
347 struct stat st;
348 long filesize;
349 void* ptr;
350 int fd;
351 binary_count=0;
352 if (stat(filename,&st)!=0) return;
353 filesize=st.st_size;
354 if ((filesize==0) || (filesize%(2*sizeof(short))!=0)) return;
355 ptr=umalloc(filesize);
356 if (!ptr) return;
357 fd=open(filename, O_RDONLY, 0777);
358 if (fd) {
359  read(fd, ptr, filesize);
360  close(fd);
361  binary_list=ptr;
362  binary_count=filesize/(2*sizeof(short));
363 }
364 else   ufree(ptr);
365}
366
367void unload_bad_pixels_list_b(void){
368 if (binary_list) ufree(binary_list);
369 binary_list=NULL;
370 binary_count=0;
371}
372
373void patch_bad_pixels_b(void){
374 int i;
375 short* ptr=binary_list;
376 for (i=0; i<binary_count; i++, ptr+=2) if (get_raw_pixel(ptr[0], ptr[1])==0) patch_bad_pixel(ptr[0], ptr[1]);
377}
378/*
379void unpatch_bad_pixels_b(void){
380 int i;
381 short* ptr=binary_list;
382 for (i=0; i<binary_count; i++, ptr+=2) set_raw_pixel(ptr[0], ptr[1], 0);
383}
384*/
385int badpixel_list_loaded_b(void){
386 return binary_count;
387}
388#endif
Note: See TracBrowser for help on using the repository browser.