root/modules/curves.c

/* [<][>][^][v][top][bottom][index][help] */

DEFINITIONS

This source file includes following definitions.
  1. curve_free_data
  2. curve_load_data
  3. curve_init_mode
  4. curve_set_mode
  5. curve_set_file
  6. curveRGB_apply
  7. curveL_apply
  8. curve_apply
  9. _module_can_unload

   1 #include "camera_info.h"
   2 #include "conf.h"
   3 #include "shooting.h"
   4 #include "raw.h"
   5 #include "gui_lang.h"
   6 
   7 #include "curves.h"
   8 #include "module_def.h"
   9 
  10 /*
  11         Expands curves features
  12         
  13         RGB curves:     ouput = curve[input]
  14         L curves:               output = curve[L] *(input-black) + black
  15         RGB curves and L curves are 4 colors curves
  16         L curves contain multiplicator factor (value = multiplicator * 10^12)
  17         
  18         DR curves:              output = curve[L] *(input-black) + black
  19         DR curves are gray scale only
  20         There are 2 DR curves +1EV and +2EV gain
  21         
  22         Auto DR automatically calculate the +1EV or +2EV base on 
  23         EV under exposure selected by user to avoid highlight burnout 
  24         (using Zebra)
  25         
  26         External function added:  shooting_get_ev_correction1 (added in core/shooting)
  27         Modified gui.c for curve enable
  28         
  29         3/28/09: Fix black holes, and column skipping, use Green as luminance in Luminance curve
  30         
  31 */
  32 unsigned short *curve_data = NULL;
  33 
  34 #define CURVE_SIZE 1024
  35 #define CURVE_BYTES (CURVE_SIZE*sizeof(unsigned short))
  36 
  37 #define BLACK 32
  38 #define LIM( a ) (((a)>1023) ? 1023: a )
  39 #define RBLACK( a ) (((a)>BLACK) ? ((a)-BLACK) : 0)
  40 
  41 #define CURVE0( a, b ) (((a) * curve0[b]) >> 12)
  42 #define CURVE1( a, b ) (((a) * curve1[b]) >> 12)
  43 #define CURVE2( a, b ) (((a) * curve2[b]) >> 12)
  44 #define CURVE3( a, b ) (((a) * curve3[b]) >> 12)
  45 
  46 typedef enum {
  47         CURVE_NONE,
  48         CURVE_CUSTOM,
  49         CURVE_SYSTEM,
  50 }CURVE_TYPE;
  51 
  52 CURVE_TYPE current_curve_type = CURVE_NONE;
  53 
  54 static void curve_free_data() {
  55         free(curve_data);
  56         curve_data = NULL;
  57         current_curve_type = CURVE_NONE;
  58 }
  59 
  60 // TODO we should avoid re-loading the same file
  61 static int curve_load_data(const char *name,CURVE_TYPE curve_type) {
  62         unsigned size;
  63         FILE *fd;
  64         if (current_curve_type != curve_type) {
  65                 curve_free_data();
  66         }
  67 
  68         if (curve_type == CURVE_NONE) {
  69                 return 1;
  70         }
  71 
  72         if(!name || !*name) {
  73                 curve_free_data();
  74                 return 0;
  75         }
  76 
  77         if( curve_type == CURVE_CUSTOM ) {
  78                 size = CURVE_BYTES*4;
  79         }
  80         else {
  81                 size = CURVE_BYTES*2;
  82         }
  83         
  84         if (!curve_data)
  85                 curve_data=malloc(size);
  86 
  87         if(!curve_data) {
  88                 curve_free_data();
  89                 return 0;
  90         }
  91         fd = fopen(name, "r+b");
  92         if (!fd) {
  93                 curve_free_data();
  94                 return 0;
  95         }
  96         fread(curve_data, 1, size, fd);
  97         fclose(fd);
  98         current_curve_type = curve_type;
  99         return 1;
 100 }
 101 
 102 void curve_init_mode() {
 103         switch(conf.curve_enable) {
 104                 case 1: // custom - ensure alloc and load conf.curve_file
 105                         curve_load_data(conf.curve_file,CURVE_CUSTOM);
 106                 break;
 107                 case 2: // system - ensure alloc and load syscurve
 108                 case 3:
 109                 case 4:
 110                         curve_load_data("A/CHDK/SYSCURVES.CVF",CURVE_SYSTEM);
 111                 break;
 112                 default:
 113                         conf.curve_enable = 0;
 114                 case 0: // disabled - free
 115                         curve_free_data();
 116         }
 117 }
 118 
 119 void curve_set_mode(int value) {
 120         if((value>=0) && (value<=4)) conf.curve_enable=value;
 121         curve_init_mode();
 122 }
 123 
 124 void curve_set_file(const char *s) {
 125     int l;
 126         if(s) {
 127         if(strncmp(s,"A/",2)==0) strncpy(conf.curve_file,s,99);
 128         else {
 129             l=strlen(CURVE_DIR);
 130             strcpy(conf.curve_file,CURVE_DIR);
 131             conf.curve_file[l]='/';
 132             strncpy(&conf.curve_file[l+1],s,99-l-1);
 133         }
 134         conf.curve_file[99]=0x0;
 135         curve_init_mode();
 136         }
 137 }
 138 
 139 // TODO border pixels should not be hard coded
 140 void curveRGB_apply() {
 141         int i,j;
 142         unsigned short pixVal0, pixVal1, pixVal2;
 143         unsigned char *src;
 144 
 145         unsigned short *curve0 = curve_data;
 146         unsigned short *curve1 = curve0 + CURVE_SIZE;
 147         unsigned short *curve2 = curve1 + CURVE_SIZE;
 148         unsigned short *curve3 = curve2 + CURVE_SIZE;
 149         
 150         if (current_curve_type != CURVE_CUSTOM) 
 151                 return;
 152         
 153         // Set pointer to picture raw data in memory
 154         src = (unsigned char *) get_raw_image_addr();   
 155         
 156         
 157         // Loop through picture rows
 158         for (i=camera_sensor.raw_rows; i;i-=2){
 159                 // Loop through picture columns 
 160                 for (j=camera_sensor.raw_rowpix; j; j-=8, src+=10){
 161                         pixVal0=((0x3fc&(((unsigned short)(src[1]))<<2)) | (src[0] >> 6));
 162                         pixVal1=((0x3f0&(((unsigned short)(src[0]))<<4)) | (src[3] >> 4));
 163                                 pixVal0 = curve0[pixVal0];
 164                                 pixVal1 = curve1[pixVal1];
 165             *(src+1) = (unsigned char) ((pixVal0>>2)); // 0
 166             *src = (unsigned char) ((pixVal0<<6)|(pixVal1>>4)); //0, 1
 167 
 168                         pixVal2=((0x3c0&(((unsigned short)(src[3]))<<6)) | (src[2] >> 2));
 169                         pixVal0=((0x300&(((unsigned short)(src[2]))<<8)) | (src[5])); 
 170                                 pixVal2 = curve0[pixVal2];
 171                                 pixVal0 = curve1[pixVal0];
 172             *(src+3) = (unsigned char) ((pixVal1<<4)|(pixVal2>>6)); //1,2
 173             *(src+2) = (unsigned char) ((pixVal2<<2)|(pixVal0>>8)); //2,3 =>(2,0)
 174             *(src+5) = (unsigned char) ((pixVal0)); //3 (=>0)
 175 
 176                         pixVal0=((0x3fc&(((unsigned short)(src[4]))<<2)) | (src[7] >> 6)); 
 177                         pixVal1=((0x3f0&(((unsigned short)(src[7]))<<4)) | (src[6] >> 4)); 
 178                                 pixVal0 = curve0[pixVal0];
 179                                 pixVal1 = curve1[pixVal1];
 180             *(src+4) = (unsigned char) ((pixVal0>>2)); // 4 => 0
 181             *(src+7) = (unsigned char) ((pixVal0<<6)|(pixVal1>>4)); // 4,5 => (0,1)
 182 
 183                         pixVal2=((0x3c0&(((unsigned short)(src[6]))<<6)) | (src[9] >> 2)); 
 184                         pixVal0=((0x300&(((unsigned short)(src[9]))<<8)) | (src[8]));
 185                                 pixVal2 = curve0[pixVal2];
 186                                 pixVal0 = curve1[pixVal0];
 187             *(src+6) = (unsigned char) ((pixVal1<<4)|(pixVal2>>6)); // 5,6 => (1,2)
 188             *(src+9) = (unsigned char) ((pixVal2<<2)|(pixVal0>>8)); // 6,7 =>(2,0)
 189             *(src+8) = (unsigned char) ((pixVal0)); //7 (=>0)           }
 190                 }
 191                 for (j=camera_sensor.raw_rowpix;j; j-=8, src+=10){
 192                         pixVal0=((0x3fc&(((unsigned short)(src[1]))<<2)) | (src[0] >> 6));
 193                         pixVal1=((0x3f0&(((unsigned short)(src[0]))<<4)) | (src[3] >> 4));
 194                                 pixVal0 = curve2[pixVal0];
 195                                 pixVal1 = curve3[pixVal1];
 196             *(src+1) = (unsigned char) ((pixVal0>>2)); // 0
 197             *src = (unsigned char) ((pixVal0<<6)|(pixVal1>>4)); //0, 1
 198 
 199                         pixVal2=((0x3c0&(((unsigned short)(src[3]))<<6)) | (src[2] >> 2));
 200                         pixVal0=((0x300&(((unsigned short)(src[2]))<<8)) | (src[5])); 
 201                                 pixVal2 = curve2[pixVal2];
 202                                 pixVal0 = curve3[pixVal0];
 203             *(src+3) = (unsigned char) ((pixVal1<<4)|(pixVal2>>6)); //1,2
 204             *(src+2) = (unsigned char) ((pixVal2<<2)|(pixVal0>>8)); //2,3 =>(2,0)
 205             *(src+5) = (unsigned char) ((pixVal0)); //3 (=>0)
 206 
 207                         pixVal0=((0x3fc&(((unsigned short)(src[4]))<<2)) | (src[7] >> 6)); 
 208                         pixVal1=((0x3f0&(((unsigned short)(src[7]))<<4)) | (src[6] >> 4)); 
 209                                 pixVal0 = curve2[pixVal0];
 210                                 pixVal1 = curve3[pixVal1];
 211             *(src+4) = (unsigned char) ((pixVal0>>2)); // 4 => 0
 212             *(src+7) = (unsigned char) ((pixVal0<<6)|(pixVal1>>4)); // 4,5 => (0,1)
 213 
 214                         pixVal2=((0x3c0&(((unsigned short)(src[6]))<<6)) | (src[9] >> 2)); 
 215                         pixVal0=((0x300&(((unsigned short)(src[9]))<<8)) | (src[8]));
 216                                 pixVal2 = curve2[pixVal2];
 217                                 pixVal0 = curve3[pixVal0];
 218             *(src+6) = (unsigned char) ((pixVal1<<4)|(pixVal2>>6)); // 5,6 => (1,2)
 219             *(src+9) = (unsigned char) ((pixVal2<<2)|(pixVal0>>8)); // 6,7 =>(2,0)
 220             *(src+8) = (unsigned char) ((pixVal0)); //7 (=>0)
 221                 }
 222         }
 223 }
 224 
 225 
 226 void curveL_apply(unsigned sys_index) {
 227         int i,j;
 228         unsigned short pixVal0, pixVal1, pixVal2;
 229         unsigned char *src;
 230         
 231         unsigned short *curve0;
 232         unsigned short *curve1;
 233         unsigned short *curve2;
 234         unsigned short *curve3;
 235         if (current_curve_type == CURVE_SYSTEM) {
 236                 if (sys_index > 1) 
 237                         return;
 238                 curve0 = curve1 = curve2 = curve3 = curve_data + sys_index*CURVE_SIZE;
 239         }
 240         else if(current_curve_type == CURVE_CUSTOM) {
 241                 curve0 = curve_data;
 242                 curve1 = curve0 + CURVE_SIZE;
 243                 curve2 = curve1 + CURVE_SIZE;
 244                 curve3 = curve2 + CURVE_SIZE;
 245         } else {
 246                 return;
 247         }
 248 
 249 
 250         // Set pointer to picture raw data in memory
 251         src = (unsigned char *) get_raw_image_addr();   
 252         
 253         // Loop through picture rows
 254         for (i=camera_sensor.raw_rows; i;i-=2){
 255                 // Loop through picture columns 
 256                 for (j=camera_sensor.raw_rowpix; j; j-=8, src+=10){
 257                         pixVal0=((0x3fc&(((unsigned short)(src[1]))<<2)) | (src[0] >> 6));
 258                         pixVal1=((0x3f0&(((unsigned short)(src[0]))<<4)) | (src[3] >> 4));
 259                         if (pixVal1) {
 260                                 pixVal1 = RBLACK( pixVal1 );
 261                                 if (pixVal0) {
 262                                         pixVal0 = RBLACK( pixVal0 );
 263                                         pixVal0 = CURVE0( pixVal0, pixVal1 ) + BLACK;
 264                                         pixVal0 = LIM( pixVal0 );
 265                                 }
 266                                 pixVal1 = CURVE1( pixVal1, pixVal1 ) + BLACK;
 267                                 pixVal1 = LIM( pixVal1 );
 268                         }
 269             *(src+1) = (unsigned char) ((pixVal0>>2)); // 0
 270             *src = (unsigned char) ((pixVal0<<6)|(pixVal1>>4)); //0, 1
 271 
 272                         pixVal2=((0x3c0&(((unsigned short)(src[3]))<<6)) | (src[2] >> 2));
 273                         pixVal0=((0x300&(((unsigned short)(src[2]))<<8)) | (src[5])); 
 274                         if (pixVal0) {
 275                                 pixVal0 = RBLACK( pixVal0 );
 276                                 if (pixVal2) {
 277                                         pixVal2 = RBLACK( pixVal2 );
 278                                         pixVal2 = CURVE0( pixVal2, pixVal0 ) + BLACK;
 279                                         pixVal2 = LIM( pixVal2 );
 280                                 }
 281                                 pixVal0 = CURVE1( pixVal0, pixVal0 ) + BLACK;
 282                                 pixVal0 = LIM( pixVal0 );
 283                         }
 284             *(src+3) = (unsigned char) ((pixVal1<<4)|(pixVal2>>6)); //1,2
 285             *(src+2) = (unsigned char) ((pixVal2<<2)|(pixVal0>>8)); //2,3 =>(2,0)
 286             *(src+5) = (unsigned char) ((pixVal0)); //3 (=>0)
 287 
 288                         pixVal0=((0x3fc&(((unsigned short)(src[4]))<<2)) | (src[7] >> 6)); 
 289                         pixVal1=((0x3f0&(((unsigned short)(src[7]))<<4)) | (src[6] >> 4)); 
 290                         if (pixVal1) {
 291                                 pixVal1 = RBLACK( pixVal1 );
 292                                 if (pixVal0) {
 293                                         pixVal0 = RBLACK( pixVal0 );
 294                                         pixVal0 = CURVE0( pixVal0, pixVal1 ) + BLACK;
 295                                         pixVal0 = LIM( pixVal0 );
 296                                 }
 297                                 pixVal1 = CURVE1( pixVal1, pixVal1 ) + BLACK;
 298                                 pixVal1 = LIM( pixVal1 );
 299                         }
 300             *(src+4) = (unsigned char) ((pixVal0>>2)); // 4 => 0
 301             *(src+7) = (unsigned char) ((pixVal0<<6)|(pixVal1>>4)); // 4,5 => (0,1)
 302 
 303                         pixVal2=((0x3c0&(((unsigned short)(src[6]))<<6)) | (src[9] >> 2)); 
 304                         pixVal0=((0x300&(((unsigned short)(src[9]))<<8)) | (src[8]));
 305                         if (pixVal0) {
 306                                 pixVal0 = RBLACK( pixVal0 );
 307                                 if (pixVal2) {
 308                                         pixVal2 = RBLACK( pixVal2 );
 309                                         pixVal2 = CURVE0( pixVal2, pixVal0 ) + BLACK;
 310                                         pixVal2 = LIM( pixVal2 );
 311                                 }
 312                                 pixVal0 = CURVE1( pixVal0, pixVal0 ) + BLACK;
 313                                 pixVal0 = LIM( pixVal0 );
 314                         }
 315             *(src+6) = (unsigned char) ((pixVal1<<4)|(pixVal2>>6)); // 5,6 => (1,2)
 316             *(src+9) = (unsigned char) ((pixVal2<<2)|(pixVal0>>8)); // 6,7 =>(2,0)
 317             *(src+8) = (unsigned char) ((pixVal0)); //7 (=>0)
 318                 }
 319                 for (j=camera_sensor.raw_rowpix; j; j-=8, src+=10){
 320                         pixVal0=((0x3fc&(((unsigned short)(src[1]))<<2)) | (src[0] >> 6));
 321                         pixVal1=((0x3f0&(((unsigned short)(src[0]))<<4)) | (src[3] >> 4));
 322                         if (pixVal0) {
 323                                 pixVal0 = RBLACK( pixVal0 );
 324                                 if (pixVal1) {
 325                                         pixVal1 = RBLACK( pixVal1 );
 326                                         pixVal1 = CURVE3( pixVal1, pixVal0 ) + BLACK;
 327                                         pixVal1 = LIM( pixVal1 );
 328                                 }
 329                                 pixVal0 = CURVE2( pixVal0, pixVal0 ) + BLACK;
 330                                 pixVal0 = LIM( pixVal0 );
 331                         }
 332             *(src+1) = (unsigned char) ((pixVal0>>2)); // 0
 333             *src = (unsigned char) ((pixVal0<<6)|(pixVal1>>4)); //0, 1
 334 
 335                         pixVal2=((0x3c0&(((unsigned short)(src[3]))<<6)) | (src[2] >> 2));
 336                         pixVal0=((0x300&(((unsigned short)(src[2]))<<8)) | (src[5])); 
 337                         if (pixVal2) {
 338                                 pixVal2 = RBLACK( pixVal2 );
 339                                 if (pixVal0) {
 340                                         pixVal0 = RBLACK( pixVal0 );
 341                                         pixVal0 = CURVE3( pixVal0, pixVal2 ) + BLACK;
 342                                         pixVal0 = LIM( pixVal0 );
 343                                 }
 344                                 pixVal2 = CURVE2( pixVal2, pixVal2 ) + BLACK;
 345                                 pixVal2 = LIM( pixVal2 );
 346                         }
 347             *(src+3) = (unsigned char) ((pixVal1<<4)|(pixVal2>>6)); //1,2
 348             *(src+2) = (unsigned char) ((pixVal2<<2)|(pixVal0>>8)); //2,3 =>(2,0)
 349             *(src+5) = (unsigned char) ((pixVal0)); //3 (=>0)
 350 
 351                         pixVal0=((0x3fc&(((unsigned short)(src[4]))<<2)) | (src[7] >> 6)); 
 352                         pixVal1=((0x3f0&(((unsigned short)(src[7]))<<4)) | (src[6] >> 4)); 
 353                         if (pixVal0) {
 354                                 pixVal0 = RBLACK( pixVal0 );
 355                                 if (pixVal1) {
 356                                         pixVal1 = RBLACK( pixVal1 );
 357                                         pixVal1 = CURVE3( pixVal1, pixVal0 ) + BLACK;
 358                                         pixVal1 = LIM( pixVal1 );
 359                                 }
 360                                 pixVal0 = CURVE2( pixVal0, pixVal0 ) + BLACK;
 361                                 pixVal0 = LIM( pixVal0 );
 362                         }
 363             *(src+4) = (unsigned char) ((pixVal0>>2)); // 4 => 0
 364             *(src+7) = (unsigned char) ((pixVal0<<6)|(pixVal1>>4)); // 4,5 => (0,1)
 365 
 366                         pixVal2=((0x3c0&(((unsigned short)(src[6]))<<6)) | (src[9] >> 2)); 
 367                         pixVal0=((0x300&(((unsigned short)(src[9]))<<8)) | (src[8]));
 368                         if (pixVal2) {
 369                                 pixVal2 = RBLACK( pixVal2 );
 370                                 if (pixVal0) {
 371                                         pixVal0 = RBLACK( pixVal0 );
 372                                         pixVal0 = CURVE3( pixVal0, pixVal2 ) + BLACK;
 373                                         pixVal0 = LIM( pixVal0 );
 374                                 }
 375                                 pixVal2 = CURVE2( pixVal2, pixVal2 ) + BLACK;
 376                                 pixVal2 = LIM( pixVal2 );
 377                         }
 378             *(src+6) = (unsigned char) ((pixVal1<<4)|(pixVal2>>6)); // 5,6 => (1,2)
 379             *(src+9) = (unsigned char) ((pixVal2<<2)|(pixVal0>>8)); // 6,7 =>(2,0)
 380             *(src+8) = (unsigned char) ((pixVal0)); //7 (=>0)
 381                 }
 382         }
 383 }
 384 
 385 void curve_apply() {
 386         short EVbias = shooting_get_ev_correction1();
 387 
 388         switch(conf.curve_enable) {
 389                 case 0:
 390                         break;
 391                 case 1:         // Custom
 392                         if (current_curve_type == CURVE_CUSTOM){
 393                                 if(curve_data[0] > 1023){ // L curve contains multiplicator factors (0 Luminance has factor 1)
 394                                         curveL_apply(0);
 395                                 } else {
 396                                         curveRGB_apply();
 397                                 }
 398                         };
 399                         break;
 400                 case 2:
 401                 case 3: // +1EV,  +2EV
 402                         if (current_curve_type == CURVE_SYSTEM) curveL_apply( conf.curve_enable & 1 );
 403                         break;
 404                 case 4:         // Auto DR
 405 
 406                         if (current_curve_type == CURVE_SYSTEM) {
 407                                  if (EVbias <-128)  {  // x4 for Bias from "-1 2/3" and below 
 408                                         curveL_apply(1);
 409                                 } else if(EVbias<-32){ // x2 for Bias from "-1 1/3" to "-2/3"
 410                                         curveL_apply(0);
 411                                 }
 412                         }
 413                         break;
 414         }
 415         
 416 }
 417 
 418 
 419 // =========  MODULE INIT =================
 420 
 421 /***************** BEGIN OF AUXILARY PART *********************
 422 ATTENTION: DO NOT REMOVE OR CHANGE SIGNATURES IN THIS SECTION
 423 **************************************************************/
 424 
 425 int _module_can_unload()
 426 {
 427     return conf.curve_enable == 0;
 428 }
 429 
 430 /******************** Module Information structure ******************/
 431 
 432 libcurves_sym _libcurves = 
 433 {
 434     {
 435          0, 0, _module_can_unload, 0, 0
 436     },
 437 
 438     curve_init_mode,
 439     curve_apply,
 440     curve_set_mode,
 441     curve_set_file
 442 };
 443 
 444 ModuleInfo _module_info =
 445 {
 446     MODULEINFO_V1_MAGICNUM,
 447     sizeof(ModuleInfo),
 448     CURVES_VERSION,                             // Module version
 449 
 450     ANY_CHDK_BRANCH, 0, OPT_ARCHITECTURE,                       // Requirements of CHDK version
 451     ANY_PLATFORM_ALLOWED,               // Specify platform dependency
 452 
 453     (int32_t)"Curves (dll)",
 454     MTYPE_EXTENSION,            //Apply curves to shots. Only 10bit sensor version
 455 
 456     &_libcurves.base,
 457 
 458     CONF_VERSION,               // CONF version
 459     ANY_VERSION,                // CAM SCREEN version
 460     CAM_SENSOR_VERSION,         // CAM SENSOR version
 461     ANY_VERSION,                // CAM INFO version
 462 
 463     0,
 464 };
 465 
 466 /*************** END OF AUXILARY PART *******************/

/* [<][>][^][v][top][bottom][index][help] */