source: trunk/core/raw.c @ 1245

Revision 1245, 18.5 KB checked in by reyalp, 22 months ago (diff)

G12+SX30 Patch to disable raw/dng saving in 'low light' + cleanup from philmoz in http://chdk.setepontos.com/index.php?topic=650.msg70704#msg70704

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