source: trunk/core/raw.c @ 688

Revision 688, 12.1 KB checked in by reyalp, 4 years ago (diff)

Use cached memory for DNG bad pixel list.
Fix warning from last checkin.

  • 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_isenabled()) 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 && (!(shooting_get_prop(PROPCASE_RESOLUTION)==5)) && (!((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,conf.dng_raw&&conf.raw_dng_ext ? ".DNG" : 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=(unsigned char*)get_raw_image_addr()+y*RAW_ROWLEN+(x/8)*CAM_SENSOR_BITS_PER_PIXEL;
222#if CAM_SENSOR_BITS_PER_PIXEL==10
223 switch (x%8) {
224  case 0: addr[0]=(addr[0]&0x3F)|(value<<6); addr[1]=value>>2;                  break;
225  case 1: addr[0]=(addr[0]&0xC0)|(value>>4); addr[3]=(addr[3]&0x0F)|(value<<4); break;
226  case 2: addr[2]=(addr[2]&0x03)|(value<<2); addr[3]=(addr[3]&0xF0)|(value>>6); break;
227  case 3: addr[2]=(addr[2]&0xFC)|(value>>8); addr[5]=value;                     break;
228  case 4: addr[4]=value>>2;                  addr[7]=(addr[7]&0x3F)|(value<<6); break;
229  case 5: addr[6]=(addr[6]&0x0F)|(value<<4); addr[7]=(addr[7]&0xC0)|(value>>4); break;
230  case 6: addr[6]=(addr[6]&0xF0)|(value>>6); addr[9]=(addr[9]&0x03)|(value<<2); break;
231  case 7: addr[8]=value;                     addr[9]=(addr[9]&0xFC)|(value>>8); break;
232 }
233#else
234 #error define set_raw_pixel for sensor bit depth
235#endif
236}
237
238//-------------------------------------------------------------------
239unsigned short get_raw_pixel(unsigned int x,unsigned  int y){
240 unsigned char* addr=(unsigned char*)get_raw_image_addr()+y*RAW_ROWLEN+(x/8)*CAM_SENSOR_BITS_PER_PIXEL;
241#if CAM_SENSOR_BITS_PER_PIXEL==10
242 switch (x%8) {
243  case 0: return ((0x3fc&(((unsigned short)addr[1])<<2)) | (addr[0] >> 6));
244  case 1: return ((0x3f0&(((unsigned short)addr[0])<<4)) | (addr[3] >> 4));
245  case 2: return ((0x3c0&(((unsigned short)addr[3])<<6)) | (addr[2] >> 2));
246  case 3: return ((0x300&(((unsigned short)addr[2])<<8)) | (addr[5]));
247  case 4: return ((0x3fc&(((unsigned short)addr[4])<<2)) | (addr[7] >> 6));
248  case 5: return ((0x3f0&(((unsigned short)addr[7])<<4)) | (addr[6] >> 4));
249  case 6: return ((0x3c0&(((unsigned short)addr[6])<<6)) | (addr[9] >> 2));
250  case 7: return ((0x300&(((unsigned short)addr[9])<<8)) | (addr[8]));
251 }
252#else
253 #error define get_raw_pixel for sensor bit depth
254#endif
255 return 0;
256}
257
258//-------------------------------------------------------------------
259void patch_bad_pixel(unsigned int x,unsigned  int y){
260 int sum=0;
261 int nzero=0;
262 int i,j;
263 int val;
264 if ((x>=2) && (x<CAM_RAW_ROWPIX-2) && (y>=2) && (y<CAM_RAW_ROWS-2)) {
265  if ((conf.bad_pixel_removal==1) || conf.dng_raw) {  // interpolation or DNG saving
266   for (i=-2; i<=2; i+=2)
267    for (j=-2; j<=2; j+=2)
268     if ((i!=0) && (j!=0)) {
269      val=get_raw_pixel(x+i, y+j);
270      if (val) {sum+=val; nzero++;}
271     }
272   if (nzero) set_raw_pixel(x,y,sum/nzero);
273  }
274  else if (conf.bad_pixel_removal==2)  // or this makes RAW converter (internal/external)
275   set_raw_pixel(x,y,0);   
276 }
277}
278
279struct point{
280 int x;
281 int y;
282 struct point *next;
283} *pixel_list=NULL;
284
285void patch_bad_pixels(void){
286 struct point *pixel=pixel_list;
287 while (pixel){
288  patch_bad_pixel((*pixel).x,(*pixel).y);
289  pixel=(*pixel).next;
290 }
291}
292
293void make_pixel_list(char * ptr){
294 int x,y;
295 struct point *pixel;
296 char *endptr;
297 while(*ptr){
298  while (*ptr==' ' || *ptr=='\t') ++ptr; // whitespaces
299   x=strtol(ptr, &endptr, 0);
300   if (endptr != ptr) {
301    ptr = endptr;
302    if (*ptr++==',') {
303     while (*ptr==' ' || *ptr=='\t') ++ptr; // whitespaces
304     if (*ptr!='\n' && *ptr!='\r'){
305      y=strtol(ptr, &endptr, 0);
306      if (endptr != ptr) {
307       ptr = endptr;
308       pixel=malloc(sizeof(struct point));
309       if (pixel) {
310        (*pixel).x=x;
311        (*pixel).y=y;
312        (*pixel).next=pixel_list;
313        pixel_list=pixel;
314       }
315      }
316     }
317    }
318   }
319   while (*ptr && *ptr!='\n') ++ptr; // unless end of line
320   if (*ptr) ++ptr;
321 }
322}
323
324#define PIXELS_BUF_SIZE 8192
325void load_bad_pixels_list(const char* filename){
326    char *buf;
327    int fd;
328
329    if (filename) {
330        buf = umalloc(PIXELS_BUF_SIZE);
331        if (!buf) return;
332
333        fd = open(filename, O_RDONLY, 0777);
334        if (fd>=0) {
335            int rcnt = read(fd, buf, PIXELS_BUF_SIZE);
336            if (rcnt > 0) {
337                if (rcnt == PIXELS_BUF_SIZE)
338                    buf[PIXELS_BUF_SIZE-1] = 0;
339                else
340                    buf[rcnt] = 0;
341            }
342            close(fd);
343        }
344        make_pixel_list(buf);   
345        ufree(buf);
346    }
347
348}
349
350#if DNG_SUPPORT
351short* binary_list=NULL;
352int binary_count=0;
353
354void load_bad_pixels_list_b(char* filename){
355 struct stat st;
356 long filesize;
357 void* ptr;
358 FILE *fd;
359 binary_count=0;
360 if (stat(filename,&st)!=0) return;
361 filesize=st.st_size;
362 if ((filesize==0) || (filesize%(2*sizeof(short))!=0)) return;
363 ptr=malloc(filesize);
364 if (!ptr) return;
365 fd=fopen(filename, "rb");
366 if (fd) {
367  fread(ptr,1, filesize,fd);
368  fclose(fd);
369  binary_list=ptr;
370  binary_count=filesize/(2*sizeof(short));
371 }
372 else free(ptr);
373}
374
375void unload_bad_pixels_list_b(void){
376 if (binary_list) free(binary_list);
377 binary_list=NULL;
378 binary_count=0;
379}
380
381void patch_bad_pixels_b(void){
382 int i;
383 short* ptr=binary_list;
384 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]);
385}
386/*
387void unpatch_bad_pixels_b(void){
388 int i;
389 short* ptr=binary_list;
390 for (i=0; i<binary_count; i++, ptr+=2) set_raw_pixel(ptr[0], ptr[1], 0);
391}
392*/
393int badpixel_list_loaded_b(void){
394 return binary_count;
395}
396#endif
Note: See TracBrowser for help on using the repository browser.