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

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