source: trunk/core/raw.c @ 3422

Revision 3301, 14.0 KB checked in by reyalp, 4 months ago (diff)

preliminary implementation of script "shoot hooks", see http://chdk.setepontos.com/index.php?topic=11081.msg108530#msg108530 for discussion

  • Property svn:eol-style set to native
Line 
1#include "platform.h"
2#include "raw_buffer.h"
3#include "conf.h"
4#include "stdlib.h"
5#include "raw.h"
6#include "console.h"
7#include "math.h"
8#include "modules.h"
9#include "shot_histogram.h"
10#include "gui_lang.h"
11#include "gui_mbox.h"
12#include "cachebit.h"
13#include "remotecap_core.h"
14#include "ptp.h" // for remotecap constants
15#include "script_api.h" // for script hook
16
17//-------------------------------------------------------------------
18#define RAW_TARGET_DIRECTORY    "A/DCIM/%03dCANON"
19//#define RAW_TMP_FILENAME        "HDK_RAW.TMP"
20#define RAW_TARGET_FILENAME     "%s%04d%s"
21#define RAW_BRACKETING_FILENAME "%s%04d_%02d%s"
22
23//-------------------------------------------------------------------
24#define RAW_DEVELOP_OFF     0
25#define RAW_DEVELOP_RAW     1
26#define RAW_DEVELOP_DNG     2
27
28static char fn[64];
29static int develop_raw = RAW_DEVELOP_OFF;
30
31//-------------------------------------------------------------------
32void raw_prepare_develop(const char* filename, int prompt)
33{
34    develop_raw = RAW_DEVELOP_OFF;
35    if (filename)
36    {
37        struct stat st;
38        if ((stat(filename,&st) != 0) || (st.st_size < camera_sensor.raw_size))
39            return;
40        if (prompt)
41            gui_mbox_init((int)"", LANG_RAW_DEVELOP_MESSAGE, MBOX_BTN_OK|MBOX_TEXT_CENTER, NULL);
42        if (st.st_size == camera_sensor.raw_size)
43            develop_raw = RAW_DEVELOP_RAW;
44        else
45            develop_raw = RAW_DEVELOP_DNG;
46        strcpy(fn,filename);
47    }
48}
49
50//-------------------------------------------------------------------
51void patch_bad_pixels(void);
52//-------------------------------------------------------------------
53
54char* get_raw_image_addr(void) {
55    char *r=hook_raw_image_addr();
56    if (!conf.raw_cache) return r;
57    else return ADR_TO_CACHED(r);
58}
59
60char* get_alt_raw_image_addr(void) {    // return inactive buffer for cameras with multiple RAW buffers (otherwise return active buffer)
61    char *r=hook_alt_raw_image_addr();
62    if (!conf.raw_cache) return r;
63    else return ADR_TO_CACHED(r);
64}
65//-------------------------------------------------------------------
66
67/*
68create a new raw file and return the file descriptor from open
69name and
70create directories as need
71should only be called in raw hook
72modifies global fn
73*/
74static int raw_create_time; // time raw file was opened, for time stamp
75static int raw_br_counter;  // bracketing counter for raw suffix
76int raw_createfile(void)
77{
78    int fd;
79    char dir[32];
80
81    raw_create_time = time(NULL);
82
83    mkdir_if_not_exist("A/DCIM");
84    if (conf.raw_in_dir)
85        get_target_dir_name(dir);
86    else
87        sprintf(dir, RAW_TARGET_DIRECTORY, 100);
88
89    mkdir_if_not_exist(dir);
90
91    sprintf(fn, "%s/", dir);
92    if(raw_br_counter && conf.bracketing_add_raw_suffix && (shooting_get_drive_mode()!=1)) {
93        sprintf(fn+strlen(fn),
94                RAW_BRACKETING_FILENAME,
95                img_prefixes[conf.raw_prefix],
96                get_target_file_num(),
97                raw_br_counter,
98                conf.dng_raw&&conf.raw_dng_ext ? ".DNG" : img_exts[conf.raw_ext]);
99    } else {
100        sprintf(fn+strlen(fn),
101                RAW_TARGET_FILENAME,
102                img_prefixes[conf.raw_prefix],
103                get_target_file_num(),
104                conf.dng_raw&&conf.raw_dng_ext ? ".DNG" : img_exts[conf.raw_ext]);
105    }
106    fd = open(fn, O_WRONLY|O_CREAT, 0777);
107
108    return fd;
109}
110
111/*
112close filed opened by raw_createfile, set timestamp
113*/
114void raw_closefile(int fd)
115{
116    if(fd < 0) {
117        return;
118    }
119
120    struct utimbuf t;
121    t.actime = t.modtime = raw_create_time;
122    close(fd);
123    utime(fn, &t);
124
125}
126
127// Set in raw_savefile and used in get_raw_pixel & set_raw_pixel (for performance)
128// Don't call set/get_raw_pixel until this value is initialised
129static char *rawadr;    // Pointer to current raw image buffer
130
131// handle actual raw / dng saving to SD
132// returns 1 on successful save, otherwise 0
133static int raw_savefile(char *rawadr, char *altrawadr) {
134    int ret = 0;
135    started();
136    int timer=get_tick_count();
137    if (conf.dng_raw)
138    {
139        ret = libdng->write_dng(rawadr, altrawadr);
140    }
141    else
142    {
143        int fd = raw_createfile();
144        if(fd >= 0) {
145            // Write active RAW buffer
146            write(fd, ADR_TO_UNCACHED(rawadr), camera_sensor.raw_size);
147            ret = 1;
148            raw_closefile(fd);
149        }
150    }
151
152    if (conf.raw_timer) {
153        char txt[30];
154        timer=get_tick_count()-timer;
155        sprintf(txt, "saving time=%d", timer);
156        console_add_line(txt);
157    }
158
159    finished();
160    return ret;
161}
162
163// processing done when raw hook runs available
164void raw_process(void)
165{
166    // Get pointers to RAW buffers (will be the same on cameras that don't have two or more buffers)
167    rawadr = get_raw_image_addr();
168    char *altrawadr = get_alt_raw_image_addr();
169
170    if ((conf.save_raw && conf.dng_raw && is_raw_enabled())
171        || (remotecap_get_target() & PTP_CHDK_CAPTURE_DNGHDR))
172    {                             
173        libdng->capture_data_for_exif();
174        }
175    if (camera_info.state.state_kbd_script_run && shot_histogram_isenabled()) build_shot_histogram();
176
177    libscriptapi->shoot_hook(SCRIPT_SHOOT_HOOK_RAW);
178
179    // count/save badpixels if requested
180    if (libdng->raw_init_badpixel_bin())
181    {
182        return;
183    }
184
185    if (develop_raw != RAW_DEVELOP_OFF)
186    {
187        started();
188        if (develop_raw == RAW_DEVELOP_DNG)
189        {
190            libdng->load_dng_to_rawbuffer(fn, rawadr);
191        }
192        else
193        {
194            int fd = open(fn, O_RDONLY, 0777);
195            if (fd >= 0) {
196                read(fd, rawadr, camera_sensor.raw_size);
197                close(fd);
198            }
199        }
200#ifdef OPT_CURVES
201        if (conf.curve_enable)
202            libcurves->curve_apply();
203#endif
204        finished();
205        develop_raw = RAW_DEVELOP_OFF;
206        return;
207    }
208
209    if (conf.bad_pixel_removal) patch_bad_pixels();
210
211    shooting_bracketing();
212
213    if (conf.tv_bracket_value || conf.av_bracket_value || conf.iso_bracket_value || conf.subj_dist_bracket_value)
214    {
215        if (camera_info.state.state_shooting_progress != SHOOTING_PROGRESS_PROCESSING)
216            raw_br_counter = 1;
217        else
218            raw_br_counter++;
219    }
220    else
221        raw_br_counter=0;
222
223    // if any remote cap targets, skip local raw
224    if (remotecap_get_target())
225    {
226        camera_info.state.state_shooting_progress = SHOOTING_PROGRESS_PROCESSING;
227        remotecap_raw_available(rawadr);
228    }
229    else if (!(conf.raw_save_first_only && camera_info.state.state_shooting_progress == SHOOTING_PROGRESS_PROCESSING))
230    {
231        camera_info.state.state_shooting_progress = SHOOTING_PROGRESS_PROCESSING;
232
233        if (conf.save_raw && is_raw_enabled())
234        {
235            raw_savefile(rawadr,altrawadr);
236        }
237    }
238
239#ifdef OPT_CURVES
240    if (conf.curve_enable)
241        libcurves->curve_apply();
242#endif
243}
244
245//-------------------------------------------------------------------
246
247void set_raw_pixel(unsigned int x, unsigned int y, unsigned short value) {
248#if CAM_SENSOR_BITS_PER_PIXEL==10
249    unsigned char* addr=(unsigned char*)rawadr+y*camera_sensor.raw_rowlen+(x/8)*10;
250    switch (x%8) {
251        case 0: addr[0]=(addr[0]&0x3F)|(value<<6); addr[1]=value>>2;                  break;
252        case 1: addr[0]=(addr[0]&0xC0)|(value>>4); addr[3]=(addr[3]&0x0F)|(value<<4); break;
253        case 2: addr[2]=(addr[2]&0x03)|(value<<2); addr[3]=(addr[3]&0xF0)|(value>>6); break;
254        case 3: addr[2]=(addr[2]&0xFC)|(value>>8); addr[5]=value;                     break;
255        case 4: addr[4]=value>>2;                  addr[7]=(addr[7]&0x3F)|(value<<6); break;
256        case 5: addr[6]=(addr[6]&0x0F)|(value<<4); addr[7]=(addr[7]&0xC0)|(value>>4); break;
257        case 6: addr[6]=(addr[6]&0xF0)|(value>>6); addr[9]=(addr[9]&0x03)|(value<<2); break;
258        case 7: addr[8]=value;                     addr[9]=(addr[9]&0xFC)|(value>>8); break;
259    }
260#elif CAM_SENSOR_BITS_PER_PIXEL==12
261    unsigned char* addr=(unsigned char*)rawadr+y*camera_sensor.raw_rowlen+(x/4)*6;
262    switch (x%4) {
263        case 0: addr[0] = (addr[0]&0x0F) | (unsigned char)(value << 4);  addr[1] = (unsigned char)(value >> 4);  break;
264        case 1: addr[0] = (addr[0]&0xF0) | (unsigned char)(value >> 8);  addr[3] = (unsigned char)value;         break;
265        case 2: addr[2] = (unsigned char)(value >> 4);  addr[5] = (addr[5]&0x0F) | (unsigned char)(value << 4);  break;
266        case 3: addr[4] = (unsigned char)value; addr[5] = (addr[5]&0xF0) | (unsigned char)(value >> 8);  break;
267    }
268#elif CAM_SENSOR_BITS_PER_PIXEL==14
269    unsigned char* addr=(unsigned char*)rawadr+y*camera_sensor.raw_rowlen+(x/8)*14;
270    switch (x%8) {
271        case 0: addr[ 0]=(addr[0]&0x03)|(value<< 2); addr[ 1]=value>>6;                                                         break;
272        case 1: addr[ 0]=(addr[0]&0xFC)|(value>>12); addr[ 2]=(addr[ 2]&0x0F)|(value<< 4); addr[ 3]=value>>4;                   break;
273        case 2: addr[ 2]=(addr[2]&0xF0)|(value>>10); addr[ 4]=(addr[ 4]&0x3F)|(value<< 6); addr[ 5]=value>>2;                   break;
274        case 3: addr[ 4]=(addr[4]&0xC0)|(value>> 8); addr[ 7]=value;                                                            break;
275        case 4: addr[ 6]=value>>6;                   addr[ 9]=(addr[ 9]&0x03)|(value<< 2);                                      break;
276        case 5: addr[ 8]=value>>4;                   addr[ 9]=(addr[ 9]&0xFC)|(value>>12); addr[11]=(addr[11]&0x0F)|(value<<4); break;
277        case 6: addr[10]=value>>2;                   addr[11]=(addr[11]&0xF0)|(value>>10); addr[13]=(addr[13]&0x3F)|(value<<6); break;
278        case 7: addr[12]=value;                      addr[13]=(addr[13]&0xC0)|(value>> 8);                                      break;
279    }
280#else
281    #error define set_raw_pixel for sensor bit depth
282#endif
283}
284
285//-------------------------------------------------------------------
286unsigned short get_raw_pixel(unsigned int x,unsigned  int y) {
287#if CAM_SENSOR_BITS_PER_PIXEL==10
288    unsigned char* addr=(unsigned char*)rawadr+y*camera_sensor.raw_rowlen+(x/8)*10;
289    switch (x%8) {
290        case 0: return ((0x3fc&(((unsigned short)addr[1])<<2)) | (addr[0] >> 6));
291        case 1: return ((0x3f0&(((unsigned short)addr[0])<<4)) | (addr[3] >> 4));
292        case 2: return ((0x3c0&(((unsigned short)addr[3])<<6)) | (addr[2] >> 2));
293        case 3: return ((0x300&(((unsigned short)addr[2])<<8)) | (addr[5]));
294        case 4: return ((0x3fc&(((unsigned short)addr[4])<<2)) | (addr[7] >> 6));
295        case 5: return ((0x3f0&(((unsigned short)addr[7])<<4)) | (addr[6] >> 4));
296        case 6: return ((0x3c0&(((unsigned short)addr[6])<<6)) | (addr[9] >> 2));
297        case 7: return ((0x300&(((unsigned short)addr[9])<<8)) | (addr[8]));
298    }
299#elif CAM_SENSOR_BITS_PER_PIXEL==12
300    unsigned char* addr=(unsigned char*)rawadr+y*camera_sensor.raw_rowlen+(x/4)*6;
301    switch (x%4) {
302        case 0: return ((unsigned short)(addr[1])        << 4) | (addr[0] >> 4);
303        case 1: return ((unsigned short)(addr[0] & 0x0F) << 8) | (addr[3]);
304        case 2: return ((unsigned short)(addr[2])        << 4) | (addr[5] >> 4);
305        case 3: return ((unsigned short)(addr[5] & 0x0F) << 8) | (addr[4]);
306    }
307#elif CAM_SENSOR_BITS_PER_PIXEL==14
308    unsigned char* addr=(unsigned char*)rawadr+y*camera_sensor.raw_rowlen+(x/8)*14;
309    switch (x%8) {
310        case 0: return ((unsigned short)(addr[ 1])        <<  6) | (addr[ 0] >> 2);
311        case 1: return ((unsigned short)(addr[ 0] & 0x03) << 12) | (addr[ 3] << 4) | (addr[ 2] >> 4);
312        case 2: return ((unsigned short)(addr[ 2] & 0x0F) << 10) | (addr[ 5] << 2) | (addr[ 4] >> 6);
313        case 3: return ((unsigned short)(addr[ 4] & 0x3F) <<  8) | (addr[ 7]);
314        case 4: return ((unsigned short)(addr[ 6])        <<  6) | (addr[ 9] >> 2);
315        case 5: return ((unsigned short)(addr[ 9] & 0x03) << 12) | (addr[ 8] << 4) | (addr[11] >> 4);
316        case 6: return ((unsigned short)(addr[11] & 0x0F) << 10) | (addr[10] << 2) | (addr[13] >> 6);
317        case 7: return ((unsigned short)(addr[13] & 0x3F) <<  8) | (addr[12]);
318    }
319#else
320    #error define get_raw_pixel for sensor bit depth
321#endif
322    return 0;
323}
324
325//-------------------------------------------------------------------
326void patch_bad_pixel(unsigned int x,unsigned  int y) {
327    int sum=0;
328    int nzero=0;
329    int i,j;
330    int val;
331    if ((x>=2) && (x<camera_sensor.raw_rowpix-2) && (y>=2) && (y<camera_sensor.raw_rows-2)) {
332        if ((conf.bad_pixel_removal==1) || (conf.save_raw && conf.dng_raw)) {  // interpolation or DNG saving
333            for (i=-2; i<=2; i+=2)
334                for (j=-2; j<=2; j+=2)
335                    if ((i!=0) && (j!=0)) {
336                        val=get_raw_pixel(x+i, y+j);
337                        if (val) {sum+=val; nzero++;}
338                    }
339                if (nzero) set_raw_pixel(x,y,sum/nzero);
340        } else if (conf.bad_pixel_removal==2)  // or this makes RAW converter (internal/external)
341            set_raw_pixel(x,y,0);
342    }
343}
344
345struct point{
346    int x;
347    int y;
348    struct point *next;
349} *pixel_list=NULL;
350
351void patch_bad_pixels(void) {
352    struct point *pixel=pixel_list;
353    while (pixel) {
354        patch_bad_pixel((*pixel).x,(*pixel).y);
355        pixel=(*pixel).next;
356    }
357}
358
359int make_pixel_list(char * ptr, int size) {
360    int x,y;
361    struct point *pixel;
362    char *endptr;
363
364    if ( size <=0 ) return 0;
365
366    while(*ptr) {
367        while (*ptr==' ' || *ptr=='\t') ++ptr;    // whitespaces
368        x=strtol(ptr, &endptr, 0);
369        if (endptr != ptr) {
370            ptr = endptr;
371            if (*ptr++==',') {
372                while (*ptr==' ' || *ptr=='\t') ++ptr;    // whitespaces
373                if (*ptr!='\n' && *ptr!='\r') {
374                    y=strtol(ptr, &endptr, 0);
375                    if (endptr != ptr) {
376                        ptr = endptr;
377                        pixel=malloc(sizeof(struct point));
378                        if (pixel) {
379                            (*pixel).x=x;
380                            (*pixel).y=y;
381                            (*pixel).next=pixel_list;
382                            pixel_list=pixel;
383                        }
384                    }
385                }
386            }
387        }
388        while (*ptr && *ptr!='\n') ++ptr;    // unless end of line
389        if (*ptr) ++ptr;
390    }
391    return 0;
392}
Note: See TracBrowser for help on using the repository browser.