source: trunk/core/raw.c @ 1046

Revision 1046, 17.6 KB checked in by reyalP, 2 years ago (diff)
  • use active area when generating badpixel.bin
  • define DNG_SUPPORT by default, undef only for cameras without support (ixusizoom_sd30 only)
  • 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#include "console.h"
6#if DNG_SUPPORT
7    #include "dng.h"
8    #include "math.h"
9    #include "keyboard.h"
10    #include "action_stack.h"
11    #include "gui_draw.h"
12    #include "gui_mbox.h"
13    #include "gui_lang.h"
14#endif
15#ifdef OPT_CURVES
16    #include "curves.h"
17#endif
18#include "shot_histogram.h"
19
20//-------------------------------------------------------------------
21#define RAW_TARGET_DIRECTORY    "A/DCIM/%03dCANON"
22//#define RAW_TMP_FILENAME        "HDK_RAW.TMP"
23#define RAW_TARGET_FILENAME     "%s%04d%s"
24#define RAW_BRACKETING_FILENAME "%s%04d_%02d%s"
25
26#define PATH_BADPIXEL_BIN "A/CHDK/badpixel.bin"
27#define PATH_BAD_TMP_BIN "A/CHDK/bad_tmp.bin"
28
29//-------------------------------------------------------------------
30static char fn[64];
31static char dir[32];
32static int develop_raw=0;
33//-------------------------------------------------------------------
34void raw_prepare_develop(const char* filename){
35 if (filename) {
36  develop_raw=1;
37  strcpy(fn,filename);
38 }
39 else {
40  develop_raw=0;
41 }
42}
43
44//-------------------------------------------------------------------
45void patch_bad_pixels(void);
46//-------------------------------------------------------------------
47
48char* get_raw_image_addr(void){
49 if (!conf.raw_cache) return hook_raw_image_addr();
50 else return (char*) ((int)hook_raw_image_addr()&~CAM_UNCACHED_BIT);
51}
52
53char* get_alt_raw_image_addr(void){    // return inactive buffer for cameras with multiple RAW buffers (otherwise return active buffer)
54 if (!conf.raw_cache) return hook_alt_raw_image_addr();
55 else return (char*) ((int)hook_alt_raw_image_addr()&~CAM_UNCACHED_BIT);
56}
57
58//-------------------------------------------------------------------
59
60#if DNG_SUPPORT
61unsigned int get_bad_count_and_write_file(const char *fn){
62 int count=0;
63 unsigned short c[2];
64 FILE*f;
65 f=fopen(fn,"w+b");
66 for (c[1]=CAM_ACTIVE_AREA_Y1; c[1]<CAM_ACTIVE_AREA_Y2; c[1]++)
67   for (c[0]=CAM_ACTIVE_AREA_X1; c[0]<CAM_ACTIVE_AREA_X2; c[0]++)
68    if (get_raw_pixel(c[0],c[1])==0) { fwrite(c, 1, 4, f); count++;}
69 fclose(f);
70 return count;
71}
72
73unsigned short get_raw_pixel(unsigned int x,unsigned  int y);
74
75static unsigned char gamma[256];
76
77void fill_gamma_buf(void){
78 int i;
79 if (gamma[255]) return;
80#if defined(CAMERA_sx30) || defined(CAMERA_g12)
81 for (i=0; i<12; i++) gamma[i]=255*pow(i/255.0, 0.5);
82 for (i=12; i<64; i++) gamma[i]=255*pow(i/255.0, 0.4);
83 for (i=64; i<=255; i++) gamma[i]=255*pow(i/255.0, 0.25);
84#else
85 for (i=0; i<=255; i++) gamma[i]=255*pow(i/255.0, 0.5);
86#endif
87}
88
89
90void create_thumbnail(char* buf){
91 unsigned int i, j, x, y;
92 unsigned char r, g, b;
93 for (i=0; i<DNG_TH_HEIGHT; i++)
94   for (j=0; j<DNG_TH_WIDTH; j++) {
95    x=CAM_ACTIVE_AREA_X1+((CAM_ACTIVE_AREA_X2-CAM_ACTIVE_AREA_X1)*j)/DNG_TH_WIDTH;
96    y=CAM_ACTIVE_AREA_Y1+((CAM_ACTIVE_AREA_Y2-CAM_ACTIVE_AREA_Y1)*i)/DNG_TH_HEIGHT;
97#if cam_CFAPattern==0x02010100    // Red  Green  Green  Blue
98    r=gamma[get_raw_pixel((x/2)*2,(y/2)*2)>>(CAM_SENSOR_BITS_PER_PIXEL-8)]; // red pixel
99    g=gamma[6*(get_raw_pixel((x/2)*2+1,(y/2)*2)>>(CAM_SENSOR_BITS_PER_PIXEL-8))/10]; // green pixel
100    b=gamma[get_raw_pixel((x/2)*2+1,(y/2)*2+1)>>(CAM_SENSOR_BITS_PER_PIXEL-8)]; //blue pixel
101#elif cam_CFAPattern==0x01000201 // Green  Blue  Red  Green
102    r=gamma[get_raw_pixel((x/2)*2,(y/2)*2+1)>>(CAM_SENSOR_BITS_PER_PIXEL-8)]; // red pixel
103    g=gamma[6*(get_raw_pixel((x/2)*2,(y/2)*2)>>(CAM_SENSOR_BITS_PER_PIXEL-8))/10]; // green pixel
104    b=gamma[get_raw_pixel((x/2)*2+1,(y/2)*2)>>(CAM_SENSOR_BITS_PER_PIXEL-8)]; //blue pixel
105#else
106 #error please define new pattern here
107#endif
108    *buf++=r; *buf++=g; *buf++=b;
109   }
110}
111#endif
112//-------------------------------------------------------------------
113
114int raw_savefile() {
115    int ret = 0; 
116    int fd, m=(mode_get()&MODE_SHOOTING_MASK);
117    static struct utimbuf t;
118    static int br_counter;
119#if DNG_SUPPORT
120     struct t_data_for_exif* exif_data = NULL; 
121     char *thumbnail_buf = NULL;
122     if (conf.dng_raw) exif_data=capture_data_for_exif();
123#endif   
124    if (state_kbd_script_run && shot_histogram_isenabled()) build_shot_histogram();
125
126    // Get pointers to RAW buffers (will be the same on cameras that don't have two or more buffers)
127    char* rawadr = get_raw_image_addr();
128    char* altrawadr = get_alt_raw_image_addr();
129
130    // ! ! ! exclusively for badpixel creation ! ! !
131    // NOTE: get_bad_count_and_write_file() must be called from here and cannot be called
132    // outside of this function.
133    // TODO now that we make badpixel in code, special use of save_raw is not needed
134    // also don't need to actually save a raw when making bad pixel
135#if DNG_SUPPORT
136    if (conf.save_raw==255) conf.save_raw=get_bad_count_and_write_file(PATH_BAD_TMP_BIN);
137#endif
138    //
139
140    if (develop_raw) {
141     started();
142     fd = open(fn, O_RDONLY, 0777);
143     if (fd>=0) {
144      read(fd, get_raw_image_addr(), hook_raw_size());
145      close(fd);
146      }
147#ifdef OPT_CURVES
148     if (conf.curve_enable) curve_apply();
149#endif
150     finished();
151     develop_raw=0;
152     return 0;
153    }
154
155    if (conf.bad_pixel_removal) patch_bad_pixels();
156
157    shooting_bracketing();
158
159    if(conf.tv_bracket_value || conf.av_bracket_value || conf.iso_bracket_value || conf.subj_dist_bracket_value) {
160        if(state_shooting_progress != SHOOTING_PROGRESS_PROCESSING)
161            br_counter = 1;
162        else
163            br_counter++;
164    }
165    else
166        br_counter=0;
167
168
169    // got here second time in a row. Skip second RAW saving.
170    if (conf.raw_save_first_only && state_shooting_progress == SHOOTING_PROGRESS_PROCESSING) {
171        return 0;
172    }
173   
174    state_shooting_progress = SHOOTING_PROGRESS_PROCESSING;
175
176    if (conf.save_raw
177        && (!(shooting_get_prop(PROPCASE_RESOLUTION)==5))
178        && (!((movie_status > 1) && conf.save_raw_in_video))
179        && (!((m==MODE_SPORTS) && conf.save_raw_in_sports))
180        && (!((m==MODE_AUTO) && conf.save_raw_in_auto))
181        && (!(conf.edge_overlay_enable && conf.save_raw_in_edgeoverlay))
182        && (!((shooting_get_drive_mode()==1) && conf.save_raw_in_burst && !(m==MODE_SPORTS)))
183        && (!((shooting_get_drive_mode()>=2) && conf.save_raw_in_timer))
184        && (!((shooting_get_prop(PROPCASE_BRACKET_MODE)==1) && conf.save_raw_in_ev_bracketing)) )
185    {
186        long v;
187        int timer; char txt[30];
188
189        started();
190
191        t.actime = t.modtime = time(NULL);
192
193        mkdir("A/DCIM");
194#if defined(CAM_DATE_FOLDER_NAMING)
195        if (conf.raw_in_dir)
196            get_target_dir_name(dir);
197        else
198            sprintf(dir, RAW_TARGET_DIRECTORY, 100);
199#else
200        sprintf(dir, RAW_TARGET_DIRECTORY, (conf.raw_in_dir)?get_target_dir_num():100);
201#endif
202        mkdir(dir);
203
204        sprintf(fn, "%s/", dir);
205        if(br_counter && conf.bracketing_add_raw_suffix && (shooting_get_drive_mode()!=1)) {
206            sprintf(fn+strlen(fn),
207                    RAW_BRACKETING_FILENAME,
208                    img_prefixes[conf.raw_prefix],
209                    get_target_file_num(),
210                    br_counter,
211                    conf.dng_raw&&conf.raw_dng_ext ? ".DNG" : img_exts[conf.raw_ext]);
212        } else {
213            sprintf(fn+strlen(fn),
214                    RAW_TARGET_FILENAME,
215                    img_prefixes[conf.raw_prefix],
216                    get_target_file_num(),
217                    conf.dng_raw&&conf.raw_dng_ext ? ".DNG" : img_exts[conf.raw_ext]);
218        }
219        fd = open(fn, O_WRONLY|O_CREAT, 0777);
220        if (fd>=0) {
221            timer=get_tick_count();
222#if DNG_SUPPORT
223            if (conf.dng_raw) {
224             fill_gamma_buf();
225             create_dng_header(exif_data);
226             thumbnail_buf = malloc(DNG_TH_WIDTH*DNG_TH_HEIGHT*3);
227              if (get_dng_header() && thumbnail_buf) {
228               patch_bad_pixels_b();
229               create_thumbnail(thumbnail_buf);
230               write(fd, get_dng_header(), get_dng_header_size());
231               write(fd, thumbnail_buf, DNG_TH_WIDTH*DNG_TH_HEIGHT*3);
232               reverse_bytes_order2(rawadr, altrawadr, hook_raw_size());
233             }
234            }
235#endif
236            if (conf.dng_raw) {
237                // Write alternate (inactive) buffer that we reversed the bytes into above (if only one buffer then it will be the active buffer instead)
238                write(fd, (char*)(((unsigned long)altrawadr)|CAM_UNCACHED_BIT), hook_raw_size());
239            }
240            else
241            {
242                // Write active RAW buffer
243                write(fd, (char*)(((unsigned long)rawadr)|CAM_UNCACHED_BIT), hook_raw_size());
244            }
245            close(fd);
246            utime(fn, &t);
247#if DNG_SUPPORT
248            if (conf.dng_raw) {
249             if (get_dng_header() && thumbnail_buf) {
250                 if (rawadr == altrawadr)    // If only one RAW buffer then we have to swap the bytes back
251                    reverse_bytes_order2(rawadr, altrawadr, hook_raw_size());
252          //   unpatch_bad_pixels_b();
253              }
254             if (get_dng_header()) free_dng_header();
255             if (thumbnail_buf) free(thumbnail_buf);
256            }
257#endif
258            if (conf.raw_timer) {
259                timer=get_tick_count()-timer;
260                sprintf(txt, "saving time=%d", timer);
261                console_add_line(txt);
262            }
263        }
264
265        finished();
266
267        ret = (fd >= 0);
268    }
269
270#ifdef OPT_CURVES
271    if (conf.curve_enable) curve_apply();
272#endif
273    return ret;
274}
275
276//-------------------------------------------------------------------
277void raw_postprocess() {
278}
279
280//-------------------------------------------------------------------
281
282void set_raw_pixel(unsigned int x, unsigned int y, unsigned short value){
283#if CAM_SENSOR_BITS_PER_PIXEL==10
284 unsigned char* addr=(unsigned char*)get_raw_image_addr()+y*RAW_ROWLEN+(x/8)*CAM_SENSOR_BITS_PER_PIXEL;
285 switch (x%8) {
286  case 0: addr[0]=(addr[0]&0x3F)|(value<<6); addr[1]=value>>2;                  break;
287  case 1: addr[0]=(addr[0]&0xC0)|(value>>4); addr[3]=(addr[3]&0x0F)|(value<<4); break;
288  case 2: addr[2]=(addr[2]&0x03)|(value<<2); addr[3]=(addr[3]&0xF0)|(value>>6); break;
289  case 3: addr[2]=(addr[2]&0xFC)|(value>>8); addr[5]=value;                     break;
290  case 4: addr[4]=value>>2;                  addr[7]=(addr[7]&0x3F)|(value<<6); break;
291  case 5: addr[6]=(addr[6]&0x0F)|(value<<4); addr[7]=(addr[7]&0xC0)|(value>>4); break;
292  case 6: addr[6]=(addr[6]&0xF0)|(value>>6); addr[9]=(addr[9]&0x03)|(value<<2); break;
293  case 7: addr[8]=value;                     addr[9]=(addr[9]&0xFC)|(value>>8); break;
294 }
295#elif CAM_SENSOR_BITS_PER_PIXEL==12
296 unsigned char* addr=(unsigned char*)get_raw_image_addr()+y*RAW_ROWLEN+(x/4)*6;
297 switch (x%4) {
298  case 0: addr[0] = (addr[0]&0x0F) | (unsigned char)(value << 4);  addr[1] = (unsigned char)(value >> 4);  break;
299  case 1: addr[0] = (addr[0]&0xF0) | (unsigned char)(value >> 8);  addr[3] = (unsigned char)value;         break;
300  case 2: addr[2] = (unsigned char)(value >> 4);  addr[5] = (addr[5]&0x0F) | (unsigned char)(value << 4);  break;
301  case 3: addr[4] = (unsigned char)value; addr[5] = (addr[5]&0xF0) | (unsigned char)(value >> 8);  break;
302 }
303#else
304 #error define set_raw_pixel for sensor bit depth
305#endif
306}
307
308//-------------------------------------------------------------------
309unsigned short get_raw_pixel(unsigned int x,unsigned  int y){
310#if CAM_SENSOR_BITS_PER_PIXEL==10
311 unsigned char* addr=(unsigned char*)get_raw_image_addr()+y*RAW_ROWLEN+(x/8)*CAM_SENSOR_BITS_PER_PIXEL;
312 switch (x%8) {
313  case 0: return ((0x3fc&(((unsigned short)addr[1])<<2)) | (addr[0] >> 6));
314  case 1: return ((0x3f0&(((unsigned short)addr[0])<<4)) | (addr[3] >> 4));
315  case 2: return ((0x3c0&(((unsigned short)addr[3])<<6)) | (addr[2] >> 2));
316  case 3: return ((0x300&(((unsigned short)addr[2])<<8)) | (addr[5]));
317  case 4: return ((0x3fc&(((unsigned short)addr[4])<<2)) | (addr[7] >> 6));
318  case 5: return ((0x3f0&(((unsigned short)addr[7])<<4)) | (addr[6] >> 4));
319  case 6: return ((0x3c0&(((unsigned short)addr[6])<<6)) | (addr[9] >> 2));
320  case 7: return ((0x300&(((unsigned short)addr[9])<<8)) | (addr[8]));
321 }
322#elif CAM_SENSOR_BITS_PER_PIXEL==12
323 unsigned char* addr=(unsigned char*)get_raw_image_addr()+y*RAW_ROWLEN+(x/4)*6;
324 switch (x%4) {
325  case 0: return ((unsigned short)(addr[1]) << 4) | (addr[0] >> 4);
326  case 1: return ((unsigned short)(addr[0] & 0x0F) << 8) | (addr[3]);
327  case 2: return ((unsigned short)(addr[2]) << 4) | (addr[5] >> 4);
328  case 3: return ((unsigned short)(addr[5] & 0x0F) << 8) | (addr[4]);
329 }
330#else
331 #error define get_raw_pixel for sensor bit depth
332#endif
333 return 0;
334}
335
336//-------------------------------------------------------------------
337void patch_bad_pixel(unsigned int x,unsigned  int y){
338 int sum=0;
339 int nzero=0;
340 int i,j;
341 int val;
342 if ((x>=2) && (x<CAM_RAW_ROWPIX-2) && (y>=2) && (y<CAM_RAW_ROWS-2)) {
343  if ((conf.bad_pixel_removal==1) || conf.dng_raw) {  // interpolation or DNG saving
344   for (i=-2; i<=2; i+=2)
345    for (j=-2; j<=2; j+=2)
346     if ((i!=0) && (j!=0)) {
347      val=get_raw_pixel(x+i, y+j);
348      if (val) {sum+=val; nzero++;}
349     }
350   if (nzero) set_raw_pixel(x,y,sum/nzero);
351  }
352  else if (conf.bad_pixel_removal==2)  // or this makes RAW converter (internal/external)
353   set_raw_pixel(x,y,0);   
354 }
355}
356
357struct point{
358 int x;
359 int y;
360 struct point *next;
361} *pixel_list=NULL;
362
363void patch_bad_pixels(void){
364 struct point *pixel=pixel_list;
365 while (pixel){
366  patch_bad_pixel((*pixel).x,(*pixel).y);
367  pixel=(*pixel).next;
368 }
369}
370
371void make_pixel_list(char * ptr){
372 int x,y;
373 struct point *pixel;
374 char *endptr;
375 while(*ptr){
376  while (*ptr==' ' || *ptr=='\t') ++ptr; // whitespaces
377   x=strtol(ptr, &endptr, 0);
378   if (endptr != ptr) {
379    ptr = endptr;
380    if (*ptr++==',') {
381     while (*ptr==' ' || *ptr=='\t') ++ptr; // whitespaces
382     if (*ptr!='\n' && *ptr!='\r'){
383      y=strtol(ptr, &endptr, 0);
384      if (endptr != ptr) {
385       ptr = endptr;
386       pixel=malloc(sizeof(struct point));
387       if (pixel) {
388        (*pixel).x=x;
389        (*pixel).y=y;
390        (*pixel).next=pixel_list;
391        pixel_list=pixel;
392       }
393      }
394     }
395    }
396   }
397   while (*ptr && *ptr!='\n') ++ptr; // unless end of line
398   if (*ptr) ++ptr;
399 }
400}
401
402#define PIXELS_BUF_SIZE 8192
403void load_bad_pixels_list(const char* filename){
404    char *buf;
405    int fd;
406
407    if (filename) {
408        buf = umalloc(PIXELS_BUF_SIZE);
409        if (!buf) return;
410
411        fd = open(filename, O_RDONLY, 0777);
412        if (fd>=0) {
413            int rcnt = read(fd, buf, PIXELS_BUF_SIZE);
414            if (rcnt > 0) {
415                if (rcnt == PIXELS_BUF_SIZE)
416                buf[PIXELS_BUF_SIZE-1] = 0;
417                else
418                buf[rcnt] = 0;
419            }
420            close(fd);
421        }
422        make_pixel_list(buf);   
423        ufree(buf);
424    }
425
426}
427
428#if DNG_SUPPORT
429short* binary_list=NULL;
430int binary_count=0;
431
432void load_bad_pixels_list_b(char* filename){
433 struct stat st;
434 long filesize;
435 void* ptr;
436 FILE *fd;
437 binary_count=0;
438 if (stat(filename,&st)!=0) return;
439 filesize=st.st_size;
440 if ((filesize==0) || (filesize%(2*sizeof(short))!=0)) return;
441 ptr=malloc(filesize);
442 if (!ptr) return;
443 fd=fopen(filename, "rb");
444 if (fd) {
445  fread(ptr,1, filesize,fd);
446  fclose(fd);
447  binary_list=ptr;
448  binary_count=filesize/(2*sizeof(short));
449 }
450 else free(ptr);
451}
452
453void unload_bad_pixels_list_b(void){
454 if (binary_list) free(binary_list);
455 binary_list=NULL;
456 binary_count=0;
457}
458
459void patch_bad_pixels_b(void){
460 int i;
461 short* ptr=binary_list;
462 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]);
463}
464/*
465void unpatch_bad_pixels_b(void){
466 int i;
467 short* ptr=binary_list;
468 for (i=0; i<binary_count; i++, ptr+=2) set_raw_pixel(ptr[0], ptr[1], 0);
469}
470*/
471int badpixel_list_loaded_b(void){
472 return binary_count;
473}
474
475// -----------------------------------------------
476
477enum BadpixelFSM
478{
479    BADPIX_START,
480    BADPIX_S1,
481    BADPIX_S2
482};
483
484int badpixel_task_stack(long p)
485{
486    static unsigned int badpix_cnt1, badpix_cnt2;
487    static int raw_conf_bck;
488
489    switch(p)
490    {
491
492    case BADPIX_START:
493        action_pop();
494
495        console_clear();
496        console_add_line("Wait please... ");
497        console_add_line("This takes a few seconds,");
498        console_add_line("don't panic!");
499       
500        raw_conf_bck = conf.save_raw;
501        conf.save_raw = 255;
502       
503        shooting_set_tv96_direct(96, SET_LATER);
504        action_push(BADPIX_S1);
505        action_push(AS_SHOOT);
506        action_push_delay(3000);
507        break;
508    case BADPIX_S1:
509        action_pop();       
510
511        badpix_cnt1 = conf.save_raw;
512        conf.save_raw = 255;
513        shooting_set_tv96_direct(96, SET_LATER);
514
515        action_push(BADPIX_S2);
516        action_push(AS_SHOOT);
517        break;
518    case BADPIX_S2:
519        action_pop();
520
521        badpix_cnt2 = conf.save_raw;
522        conf.save_raw = raw_conf_bck;
523
524        console_clear();
525        if (badpix_cnt1 == badpix_cnt2)
526        {
527            // TODO script asked confirmation first
528            // should sanity check bad pixel count at least,
529            /// wrong buffer address could make badpixel bigger than available mem
530            char msg[32];
531            console_add_line("badpixel.bin created.");
532            sprintf(msg, "Bad pixel count: %d", badpix_cnt1);
533            console_add_line(msg);
534            DeleteFile_Fut(PATH_BADPIXEL_BIN);
535            RenameFile_Fut(PATH_BAD_TMP_BIN,PATH_BADPIXEL_BIN);
536        }
537        else
538        {
539            console_add_line("badpixel.bin failed.");
540            console_add_line("Please try again.");
541        }
542        DeleteFile_Fut(PATH_BAD_TMP_BIN);
543
544        action_push_delay(3000);
545        break;
546    default:
547        action_stack_standard(p);
548        break;
549    }
550   
551    return 1;
552}
553
554
555void create_badpixel_bin()
556{
557    if (!(mode_get() & MODE_REC))
558    {
559        gui_mbox_init(LANG_ERROR, LANG_MSG_RECMODE_REQUIRED, MBOX_BTN_OK|MBOX_TEXT_CENTER, NULL);
560        return;
561    }
562       
563    gui_set_mode(GUI_MODE_ALT);
564    action_stack_create(&badpixel_task_stack, BADPIX_START);
565}
566
567#endif
Note: See TracBrowser for help on using the repository browser.