source: trunk/core/raw.c @ 597

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