root/modules/rawhookops.c

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

DEFINITIONS

This source file includes following definitions.
  1. round_d2i
  2. rawop_get_cfa
  3. rawop_get_cfa_offsets
  4. rawop_get_bits_per_pixel
  5. rawop_get_raw_neutral
  6. rawop_get_black_level
  7. rawop_get_white_level
  8. rawop_get_raw_width
  9. rawop_get_raw_height
  10. rawop_get_active_left
  11. rawop_get_active_top
  12. rawop_get_active_width
  13. rawop_get_active_height
  14. rawop_get_jpeg_left
  15. rawop_get_jpeg_top
  16. rawop_get_jpeg_width
  17. rawop_get_jpeg_height
  18. rawop_get_pixel
  19. rawop_set_pixel
  20. rawop_get_pixels_rgbg
  21. rawop_set_pixels_rgbg
  22. rawop_fill_rect
  23. rawop_meter
  24. rawop_raw_to_ev
  25. rawop_ev_to_raw
  26. rawop_create_histogram
  27. rawop_histo_update
  28. rawop_histo_range
  29. rawop_histo_total_pixels
  30. rawop_histo_bits
  31. rawop_histo_free
  32. rawop_histo_gc
  33. init_raw_params
  34. rawop_update_hook_status
  35. luaopen_rawop

   1 /*
   2 functions for operating on raw framebuffer from script hooks
   3 */
   4 #include "camera_info.h"
   5 #include "conf.h"
   6 #include "raw.h"
   7 #include "math.h"
   8 
   9 #include "lualib.h"
  10 #include "lauxlib.h"
  11 
  12 extern void set_number_field(lua_State *L, const char *name, int value);
  13 
  14 // set when in hook and capture mode supports raw
  15 static int raw_buffer_valid;
  16 
  17 // TODO not really the same for R,G,B
  18 // raw value of a neutral exposure, including black level
  19 static unsigned raw_neutral;
  20 // log2(raw_neutral - blacklevel), i.e. the range of significant raw values
  21 static double log2_raw_neutral_count; 
  22 
  23 // offsets of bayer elements from an even pixel coordinate
  24 // [r,g,g,b][x,y]
  25 static unsigned cfa_offsets[4][2];
  26 static const char *cfa_names[]={"r","g1","g2","b"};
  27 #define CFA_R 0
  28 #define CFA_G1 1
  29 #define CFA_G2 2
  30 #define CFA_B 3
  31 #define RAWOP_HISTO_META "rawop.histo_meta"
  32 
  33 // simple round half away from zero
  34 static int round_d2i(double v) {
  35     if(v<0.0) {
  36         return (int)(v - 0.5);
  37     }
  38     return (int)(v + 0.5);
  39 }
  40 /*
  41 cfa=rawop.get_cfa()
  42 return: CFA pattern as a 32 bit interger, as used in DNG
  43 */
  44 static int rawop_get_cfa(lua_State *L) {
  45     lua_pushnumber(L,camera_sensor.cfa_pattern);
  46     return 1;
  47 }
  48 
  49 /*
  50 cfa_offsets=rawop.get_cfa_offsets()
  51 returns: offsets of color filter elements with respect to an even valued x,y pair, in the form
  52 {
  53  r={ y=1, x=0, },
  54  g1={ y=0, x=0, },
  55  b={ y=0, x=1, },
  56  g2={ y=1, x=1, },
  57 }
  58 */
  59 static int rawop_get_cfa_offsets(lua_State *L) {
  60     lua_createtable(L, 0, 4);
  61     int i;
  62     for(i=0;i<4;i++) {
  63         lua_createtable(L, 0, 2);
  64         set_number_field(L,"x",cfa_offsets[i][0]);
  65         set_number_field(L,"y",cfa_offsets[i][1]);
  66         lua_setfield(L, -2, cfa_names[i]);
  67     }
  68     return 1;
  69 }
  70 
  71 /*
  72 bpp=rawop.get_bits_per_pixel()
  73 returns: sensor bit depth (10, 12, or 14 in currently supported cameras)
  74 */
  75 static int rawop_get_bits_per_pixel(lua_State *L) {
  76     lua_pushnumber(L,camera_sensor.bits_per_pixel);
  77     return 1;
  78 }
  79 
  80 /*
  81 neutral=rawop.get_raw_neutral()
  82 returns: approximate raw value of a neutral grey target exposed with canon AE
  83 raw_to_ev96(netural) = 0
  84 This is not aware of CFA, it is based on an average of all color elements
  85 
  86 NOTE on G1x, the value may change depending on ISO settings. The value is only
  87 updated when the raw hook is entered for the shot so for maximum portability,
  88 this function should only be called inside the raw hook.
  89 */
  90 static int rawop_get_raw_neutral(lua_State *L) {
  91     lua_pushnumber(L,(int)raw_neutral);
  92     return 1;
  93 }
  94 
  95 /*
  96 bl=rawop.get_black_level()
  97 returns: sensor black level value
  98 
  99 NOTE on G1x, the value may change depending on ISO settings. The value is only
 100 updated when the raw hook is entered for the shot so for maximum portability,
 101 this function should only be called inside the raw hook.
 102 */
 103 static int rawop_get_black_level(lua_State *L) {
 104     lua_pushnumber(L,camera_sensor.black_level);
 105     return 1;
 106 }
 107 
 108 /*
 109 wl=rawop.get_white_level()
 110 returns: sensor white level value (2^bpp - 1 for all known sensors)
 111 */
 112 static int rawop_get_white_level(lua_State *L) {
 113     lua_pushnumber(L,camera_sensor.white_level);
 114     return 1;
 115 }
 116 
 117 /*
 118 w=rawop.get_raw_width()
 119 returns: width of the raw buffer, in pixels
 120 */
 121 static int rawop_get_raw_width(lua_State *L) {
 122     lua_pushnumber(L,camera_sensor.raw_rowpix);
 123     return 1;
 124 }
 125 
 126 /*
 127 h=rawop.get_raw_height()
 128 returns height of the raw buffer, in pixels
 129 */
 130 static int rawop_get_raw_height(lua_State *L) {
 131     lua_pushnumber(L,camera_sensor.raw_rows);
 132     return 1;
 133 }
 134 
 135 /*
 136 active area functions
 137 
 138 NOTES
 139 Active area is defined in the port, and is not affected by the "Crop size" DNG menu option
 140 
 141 Active area may include dark borders of pixels which contain image data, but are not exposed
 142 the same as the majority of the sensor. JPEG area may be a better choice for whole scene
 143 measurements.
 144 */
 145 
 146 /*
 147 left=rawop.get_active_left()
 148 returns: x coordinate of the leftmost pixel containing valid data in the raw buffer
 149 */
 150 static int rawop_get_active_left(lua_State *L) {
 151     lua_pushnumber(L,camera_sensor.active_area.x1);
 152     return 1;
 153 }
 154 
 155 /*
 156 top=rawop.get_active_top()
 157 returns: y coordinate of the topmost pixel containing valid data in the raw buffer
 158 */
 159 static int rawop_get_active_top(lua_State *L) {
 160     lua_pushnumber(L,camera_sensor.active_area.y1);
 161     return 1;
 162 }
 163 
 164 /*
 165 w=rawop.get_active_width()
 166 returns: width of the active area, in pixels
 167 */
 168 static int rawop_get_active_width(lua_State *L) {
 169     lua_pushnumber(L,camera_sensor.active_area.x2 - camera_sensor.active_area.x1);
 170     return 1;
 171 }
 172 
 173 /*
 174 h=rawop.get_active_height()
 175 returns: height of the active area, in pixels
 176 */
 177 static int rawop_get_active_height(lua_State *L) {
 178     lua_pushnumber(L,camera_sensor.active_area.y2 - camera_sensor.active_area.y1);
 179     return 1;
 180 }
 181 
 182 /*
 183 JPEG area functions
 184 
 185 NOTES
 186 JPEG area is defined in the port, and is not affected by the "Crop size" DNG menu option
 187 
 188 JPEG area represents the approximate area of the sensor used for the JPEG, but may not
 189 exactly match either the pixel dimensions or sensor area.
 190 
 191 These functions return sensor coordinates, not active area relative coordinates used
 192 in DNG metadata.
 193 
 194 JPEG area generally will not include the dark borders that can affect active area, so jpeg
 195 area is a good choice for measuring the whole scene.
 196 */
 197 
 198 /*
 199 left=rawop.get_jpeg_left()
 200 returns: x coordinate of the leftmost pixel of the jpeg area, in sensor coordinates
 201 */
 202 static int rawop_get_jpeg_left(lua_State *L) {
 203     lua_pushnumber(L,camera_sensor.active_area.x1 + camera_sensor.jpeg.x);
 204     return 1;
 205 }
 206 
 207 /*
 208 top=rawop.get_jpeg_top()
 209 returns: y coordinate of the topmost pixel of the jpeg area, in sensor coordinates
 210 */
 211 static int rawop_get_jpeg_top(lua_State *L) {
 212     lua_pushnumber(L,camera_sensor.active_area.y1 + camera_sensor.jpeg.y);
 213     return 1;
 214 }
 215 
 216 /*
 217 width=rawop.get_jpeg_width()
 218 returns: width of the jpeg area, in pixels
 219 */
 220 static int rawop_get_jpeg_width(lua_State *L) {
 221     lua_pushnumber(L,camera_sensor.jpeg.width);
 222     return 1;
 223 }
 224 
 225 /*
 226 height=rawop.get_jpeg_height()
 227 returns: height of the jpeg area, in pixels
 228 */
 229 static int rawop_get_jpeg_height(lua_State *L) {
 230     lua_pushnumber(L,camera_sensor.jpeg.height);
 231     return 1;
 232 }
 233 
 234 
 235 /*
 236 raw buffer access functions
 237 */
 238 /*
 239 v=rawop.get_pixel(x,y)
 240 return: raw value, or nil if out of bounds
 241 
 242 An error is generated if the this function is called outside the raw hook, or in a shooting
 243 mode for which raw data is not available.
 244 */
 245 static int rawop_get_pixel(lua_State *L) {
 246     if(!raw_buffer_valid) {
 247         return luaL_error(L,"raw data not available");
 248     }
 249     unsigned x=luaL_checknumber(L,1);
 250     unsigned y=luaL_checknumber(L,2);
 251     // TODO return nil for out of bounds?
 252     // might not want to check, or return 0, or error()?
 253     if(x >= (unsigned)camera_sensor.raw_rowpix || y >= (unsigned)camera_sensor.raw_rows) {
 254         return 0;
 255     }
 256     lua_pushnumber(L,get_raw_pixel(x,y));
 257     return 1;
 258 }
 259 
 260 /*
 261 rawop.set_pixel(x,y,v)
 262 sets pixel to v
 263 
 264 An error is generated if the this function is called outside the raw hook, or in a shooting
 265 mode for which raw data is not available.
 266 */
 267 static int rawop_set_pixel(lua_State *L) {
 268     if(!raw_buffer_valid) {
 269         return luaL_error(L,"raw data not available");
 270     }
 271     unsigned int x=luaL_checknumber(L,1);
 272     unsigned int y=luaL_checknumber(L,2);
 273     unsigned short v=luaL_checknumber(L,3);
 274     // TODO
 275     // might want to or error()?
 276     if(x >= (unsigned)camera_sensor.raw_rowpix || y >= (unsigned)camera_sensor.raw_rows) {
 277         return 0;
 278     }
 279     // TODO could check v
 280     set_raw_pixel(x,y,v);
 281     return 0;
 282 }
 283 
 284 /*
 285 r,g1,b,g2=rawop.get_pixels_rgbg(x,y)
 286 returns: values of the CFA quad containing x,y or nil if out of bounds
 287 x and y are truncated to the nearest even value.
 288 
 289 An error is generated if the this function is called outside the raw hook, or in a shooting
 290 mode for which raw data is not available.
 291 */
 292 static int rawop_get_pixels_rgbg(lua_State *L) {
 293     if(!raw_buffer_valid) {
 294         return luaL_error(L,"raw data not available");
 295     }
 296     unsigned int x=luaL_checknumber(L,1);
 297     unsigned int y=luaL_checknumber(L,2);
 298 
 299     x &= 0xFFFFFFFE;
 300     y &= 0xFFFFFFFE;
 301 
 302     if(x >= (unsigned)camera_sensor.raw_rowpix || y >= (unsigned)camera_sensor.raw_rows) {
 303         return 0;
 304     }
 305     lua_pushnumber(L,get_raw_pixel(x+cfa_offsets[CFA_R][0],y+cfa_offsets[CFA_R][1]));
 306     lua_pushnumber(L,get_raw_pixel(x+cfa_offsets[CFA_G1][0],y+cfa_offsets[CFA_G1][1]));
 307     lua_pushnumber(L,get_raw_pixel(x+cfa_offsets[CFA_B][0],y+cfa_offsets[CFA_B][1]));
 308     lua_pushnumber(L,get_raw_pixel(x+cfa_offsets[CFA_G2][0],y+cfa_offsets[CFA_G2][1]));
 309     return 4;
 310 }
 311 
 312 /*
 313 rawop.set_pixels_rgbg(x,y,r,g1,b[,g2])
 314 sets the values of the CFA quad containing x,y
 315 if g2 is not specified, it is set to g1
 316 x and y are truncated to the nearest even value.
 317 
 318 An error is generated if the this function is called outside the raw hook, or in a shooting
 319 mode for which raw data is not available.
 320 */
 321 static int rawop_set_pixels_rgbg(lua_State *L) {
 322     if(!raw_buffer_valid) {
 323         return luaL_error(L,"raw data not available");
 324     }
 325     unsigned int x=luaL_checknumber(L,1);
 326     unsigned int y=luaL_checknumber(L,2);
 327     unsigned short r=luaL_checknumber(L,3);
 328     unsigned short g1=luaL_checknumber(L,4);
 329     unsigned short b=luaL_checknumber(L,5);
 330     unsigned short g2=luaL_optnumber(L,6,g1);
 331 
 332     x &= 0xFFFFFFFE;
 333     y &= 0xFFFFFFFE;
 334 
 335     if(x >= (unsigned)camera_sensor.raw_rowpix - 1 || y >= (unsigned)camera_sensor.raw_rows - 1) {
 336         return 0;
 337     }
 338     set_raw_pixel(x+cfa_offsets[CFA_R][0],y+cfa_offsets[CFA_R][1],r);
 339     set_raw_pixel(x+cfa_offsets[CFA_G1][0],y+cfa_offsets[CFA_G1][1],g1);
 340     set_raw_pixel(x+cfa_offsets[CFA_B][0],y+cfa_offsets[CFA_B][1],b);
 341     set_raw_pixel(x+cfa_offsets[CFA_G2][0],y+cfa_offsets[CFA_G2][1],g2);
 342     return 0;
 343 }
 344 
 345 /*
 346 rawop.fill_rect(x,y,width,height,val[,xstep[,ystep]])
 347 sets every step-th pixel of the specified rectangle to the specified value
 348 width and height out of bounds are clipped
 349 xstep defaults to 1, ystep defaults to xstep
 350 step 2 can be used with cfa offsets to fill RGB
 351 
 352 An error is generated if the this function is called outside the raw hook, or in a shooting
 353 mode for which raw data is not available.
 354 */
 355 static int rawop_fill_rect(lua_State *L) {
 356     if(!raw_buffer_valid) {
 357         return luaL_error(L,"raw data not available");
 358     }
 359     unsigned int xstart=luaL_checknumber(L,1);
 360     unsigned int ystart=luaL_checknumber(L,2);
 361     unsigned int width=luaL_checknumber(L,3);
 362     unsigned int height=luaL_checknumber(L,4);
 363     unsigned short val=luaL_checknumber(L,5);
 364     unsigned int xstep=luaL_optnumber(L,6,1);
 365     unsigned int ystep=luaL_optnumber(L,7,xstep);
 366     unsigned int xmax = xstart + width;
 367     unsigned int ymax = ystart + height;
 368     if(xstart >= (unsigned)camera_sensor.raw_rowpix || ystart >= (unsigned)camera_sensor.raw_rows) {
 369         return 0;
 370     }
 371     if(xmax > (unsigned)camera_sensor.raw_rowpix) {
 372         xmax = (unsigned)camera_sensor.raw_rowpix; 
 373     }
 374     if(ymax > (unsigned)camera_sensor.raw_rows) {
 375         ymax = (unsigned)camera_sensor.raw_rows;
 376     }
 377     unsigned x,y;
 378     for(y=ystart; y<ymax; y+=ystep) {
 379         for(x=xstart; x<xmax; x+=xstep) {
 380             set_raw_pixel(x,y,val);
 381         }
 382     }
 383     return 0;
 384 }
 385 
 386 /*
 387 mean_raw_val=rawop.meter(x,y,x_count,y_count,x_step,y_step)
 388 returns: average values of count pixels in x and y, sampled at step size step,
 389 or nil if the range is invalid or the total number of pixels could result in overflow
 390 
 391 An error is generated if the this function is called outside the raw hook, or in a shooting
 392 mode for which raw data is not available.
 393 
 394 To prevent overflow, the total number of pixels must less unsigned_max / white_level.
 395 Limits are roughly 
 396 10 bpp = 4 Mpix
 397 12 bpp = 1 Mpix
 398 14 bpp = 256 Kpix
 399 To meter larger numbers of pixels, use multiple calls and average the results
 400 
 401 To meter R G B separately, use multiple meter calls with the appropriate CFA offset and even steps
 402 To ensure all CFA colors are included in a single call, use odd steps
 403 */
 404 static int rawop_meter(lua_State *L) {
 405     if(!raw_buffer_valid) {
 406         return luaL_error(L,"raw data not available");
 407     }
 408     unsigned x1=luaL_checknumber(L,1);
 409     unsigned y1=luaL_checknumber(L,2);
 410     unsigned x_count=luaL_checknumber(L,3);
 411     unsigned y_count=luaL_checknumber(L,4);
 412     unsigned x_step=luaL_checknumber(L,5);
 413     unsigned y_step=luaL_checknumber(L,6);
 414 
 415     // no pixels
 416     if(!x_count || !y_count) {
 417         return 0;
 418     }
 419 
 420     unsigned x_max = x1 + x_step * x_count;
 421     unsigned y_max = y1 + y_step * y_count;
 422     // x out of range
 423     if(x_max > (unsigned)camera_sensor.raw_rowpix) {
 424         return 0;
 425     }
 426     // y out of range
 427     if(y_max > (unsigned)camera_sensor.raw_rows) {
 428         return 0;
 429     }
 430     // overflow possible (int max)/total  < max value 
 431     if(x_count*y_count > (unsigned)0xFFFFFFFF >> camera_sensor.bits_per_pixel) {
 432         return 0;
 433     }
 434     unsigned t=0;
 435     unsigned x,y;
 436     for(y = y1; y < y_max; y += y_step) {
 437         for(x = x1; x < x_max; x += x_step) {
 438             t+=get_raw_pixel(x,y);
 439         }
 440     }
 441     lua_pushnumber(L,t/(x_count*y_count));
 442     return 1;
 443 }
 444 
 445 /*
 446 raw value conversion functions
 447 */
 448 /*
 449 ev96=rawop.raw_to_ev(rawval[,scale])
 450 convert a raw value (blacklevel+1 to whitelevel) into an APEX EV relative to neutral
 451 if rawval is <= to blacklevel, it is clamped to blacklevel + 1.
 452 values > whitelevel are converted normally
 453 
 454 scale optionally scales the APEX value, default 96 to be compatible with camera
 455 exposure parameters. Use 1000 for imath APEX values or 96000 for APEX96 with imath
 456 
 457 NOTE on G1x, the result may change depending on ISO settings. The value is only
 458 updated when the raw hook is entered for the shot so for maximum portability,
 459 this function should only be called inside the raw hook.
 460 */
 461 static int rawop_raw_to_ev(lua_State *L) {
 462     int v=luaL_checknumber(L,1);
 463     int scale=luaL_optnumber(L,2,96);
 464     // TODO not clear what we should return, minimum real value for now
 465     if( v <= camera_sensor.black_level) {
 466         v = camera_sensor.black_level+1;
 467     }
 468     int r=round_d2i((double)scale*(log2(v - camera_sensor.black_level) - log2_raw_neutral_count));
 469     lua_pushnumber(L,r);
 470     return 1;
 471 }
 472 
 473 /*
 474 rawval=rawop.ev_to_raw(ev[,scale])
 475 Convert an APEX EV (offset from raw_neutral) to a raw value. No range checking is done
 476 
 477 scale optionally scales the APEX value, default 96 to be compatible with camera
 478 exposure parameters. Use 1000 for imath or 96000 for APEX96 with imath
 479 
 480 NOTE on G1x, the result may change depending on ISO settings. The value is only
 481 updated when the raw hook is entered for the shot so for maximum portability,
 482 this function should only be called inside the raw hook.
 483 */
 484 static int rawop_ev_to_raw(lua_State *L) {
 485     int v=luaL_checknumber(L,1);
 486     int scale=luaL_optnumber(L,2,96);
 487     // TODO not clear if this should be clamped to valid raw ranges?
 488     lua_pushnumber(L,round_d2i(pow(2,(double)v/(double)scale+log2_raw_neutral_count)+camera_sensor.black_level));
 489     return 1;
 490 }
 491 
 492 
 493 /*
 494 histogram functions and methods
 495 */
 496 typedef struct {
 497     unsigned bits;
 498     unsigned entries;
 499     unsigned total_pixels;
 500     unsigned *data;
 501 } rawop_histo_t;
 502 /*
 503 create new histogram object
 504 histo=rawop.create_histogram()
 505 */
 506 static int rawop_create_histogram(lua_State *L) {
 507     rawop_histo_t *h = (rawop_histo_t *)lua_newuserdata(L,sizeof(rawop_histo_t));
 508     if(!h) {
 509         return luaL_error(L,"failed to create userdata");
 510     }
 511     h->total_pixels = 0;
 512     h->data = NULL;
 513     luaL_getmetatable(L, RAWOP_HISTO_META);
 514     lua_setmetatable(L, -2);
 515     return 1;
 516 }
 517 
 518 /*
 519 update histogram data using specified area of raw buffer
 520 histo:update(top,left,width,height,xstep,ystep[,bits])
 521 bits specifies the bit depth of histogram. defaults to camera bit depth
 522 must be <= camera bit depth
 523 amount of memory required for the histogram data is determined by bits
 524 
 525 An error is generated if the this function is called outside the raw hook, or in a shooting
 526 mode for which raw data is not available.
 527 */
 528 static int rawop_histo_update(lua_State *L) {
 529     if(!raw_buffer_valid) {
 530         return luaL_error(L,"raw data not available");
 531     }
 532     rawop_histo_t *h = (rawop_histo_t *)luaL_checkudata(L,1,RAWOP_HISTO_META);
 533 
 534     unsigned xstart=luaL_checknumber(L,2);
 535     unsigned ystart=luaL_checknumber(L,3);
 536     unsigned width=luaL_checknumber(L,4);
 537     unsigned height=luaL_checknumber(L,5);
 538     unsigned xstep=luaL_checknumber(L,6);
 539     unsigned ystep=luaL_checknumber(L,7);
 540     int bits=luaL_optnumber(L,8,camera_sensor.bits_per_pixel);
 541     if(bits > camera_sensor.bits_per_pixel || bits < 1) {
 542         return luaL_error(L,"invalid bit depth");
 543     }
 544     unsigned shift = camera_sensor.bits_per_pixel - bits;
 545     unsigned entries = 1 << bits;
 546 
 547     h->total_pixels=0;
 548     if(xstart >= (unsigned)camera_sensor.raw_rowpix 
 549         || ystart >= (unsigned)camera_sensor.raw_rows
 550         || xstep == 0 || ystep == 0
 551         || width == 0 || height == 0) {
 552         luaL_error(L,"invalid update area");
 553         return 0;
 554     }
 555     unsigned xmax=xstart+width;
 556     unsigned ymax=ystart+height;
 557     if(xmax > (unsigned)camera_sensor.raw_rowpix) {
 558         xmax = (unsigned)camera_sensor.raw_rowpix; 
 559     }
 560     if(ymax > (unsigned)camera_sensor.raw_rows) {
 561         ymax = (unsigned)camera_sensor.raw_rows;
 562     }
 563     // total with clipping and rounding accounted for
 564     h->total_pixels=((1+(xmax - xstart - 1)/xstep))*((1+(ymax - ystart - 1)/ystep));
 565 
 566     // TODO shorts or ints based on total pixels
 567     if(h->entries != entries || !h->data) {
 568         free(h->data);
 569         h->data = malloc(entries*sizeof(unsigned));
 570         if(!h->data) {
 571             h->total_pixels=0;
 572             return luaL_error(L,"insufficient memory");
 573         }
 574     }
 575     h->entries = entries;
 576     h->bits = bits;
 577     memset(h->data,0,h->entries*sizeof(unsigned));
 578 
 579     unsigned x,y;
 580     if(shift) {
 581         for(y=ystart;y<ymax;y+=ystep) {
 582             for(x=xstart;x<xmax;x+=xstep) {
 583                 h->data[get_raw_pixel(x,y)>>shift]++;
 584             }
 585         }
 586     } else {
 587         for(y=ystart;y<ymax;y+=ystep) {
 588             for(x=xstart;x<xmax;x+=xstep) {
 589                 h->data[get_raw_pixel(x,y)]++;
 590             }
 591         }
 592     }
 593     return 0;
 594 }
 595 
 596 /*
 597 frac=histo:range(min,max[,'count'|scale])
 598 returns number of values in range, either as a fraction in parts per scale, or total count
 599 */
 600 static int rawop_histo_range(lua_State *L) {
 601     rawop_histo_t *h = (rawop_histo_t *)luaL_checkudata(L,1,RAWOP_HISTO_META);
 602     if(!h->data) {
 603         return luaL_error(L,"no data");
 604     }
 605     unsigned minval=luaL_checknumber(L,2);
 606     unsigned maxval=luaL_checknumber(L,3);
 607     int scale=1000;
 608     if(lua_gettop(L) >= 4 && !lua_isnil(L,4)) {
 609         const char *s=lua_tostring(L,4);
 610         if(!s || strcmp(s,"count") != 0) {
 611             scale=lua_tonumber(L,4);
 612             // scale could be 0 from error passing 0, but neither is valid
 613             if(!scale) {
 614                 return luaL_error(L,"invalid format");
 615             }
 616         } else {
 617             scale=0;
 618         }
 619     }
 620     if(maxval >= h->entries || minval > maxval) {
 621         return luaL_error(L,"invalid range");
 622     }
 623     // TODO error?
 624     if(!h->total_pixels) {
 625         return luaL_error(L,"no pixels");
 626 //        lua_pushnumber(L,0);
 627 //        return 1;
 628     }
 629 
 630     unsigned count=0;
 631     unsigned i;
 632     for(i=minval;i<=maxval;i++) {
 633         count+=h->data[i];
 634     }
 635     // TODO full raw buffer count*1000 could overflow 32 bit int
 636     // could check / work around using ints but probably not worth it
 637     if(scale) {
 638         lua_pushnumber(L,round_d2i((scale*(double)count)/(double)h->total_pixels));
 639     } else {
 640         lua_pushnumber(L,count);
 641     }
 642     return 1;
 643 }
 644 
 645 /*
 646 total=histo:total_pixels()
 647 returns: total number of pixels sampled
 648 */
 649 static int rawop_histo_total_pixels(lua_State *L) {
 650     rawop_histo_t *h = (rawop_histo_t *)luaL_checkudata(L,1,RAWOP_HISTO_META);
 651     if(!h->data) {
 652         return luaL_error(L,"no data");
 653     }
 654     lua_pushnumber(L,h->total_pixels);
 655     return 1;
 656 }
 657 
 658 /*
 659 bits=histo:bits()
 660 returns bit depth of histogram
 661 */
 662 static int rawop_histo_bits(lua_State *L) {
 663     rawop_histo_t *h = (rawop_histo_t *)luaL_checkudata(L,1,RAWOP_HISTO_META);
 664     if(!h->data) {
 665         return luaL_error(L,"no data");
 666     }
 667     lua_pushnumber(L,h->bits);
 668     return 1;
 669 }
 670 
 671 /*
 672 histo:free()
 673 free memory used by histogram data. histo:update must be called again to before any other functions
 674 */
 675 static int rawop_histo_free(lua_State *L) {
 676     rawop_histo_t *h = (rawop_histo_t *)luaL_checkudata(L,1,RAWOP_HISTO_META);
 677     free(h->data);
 678     h->data=NULL;
 679     return 0;
 680 }
 681 
 682 static int rawop_histo_gc(lua_State *L) {
 683     rawop_histo_free(L);
 684     return 0;
 685 }
 686 
 687 static const luaL_Reg rawop_histo_meta_methods[] = {
 688   {"__gc", rawop_histo_gc},
 689   {NULL, NULL}
 690 };
 691 
 692 static const luaL_Reg rawop_histo_methods[] = {
 693   {"update", rawop_histo_update},
 694   {"range", rawop_histo_range},
 695   {"total_pixels", rawop_histo_total_pixels},
 696   {"bits", rawop_histo_bits},
 697   {"free", rawop_histo_free},
 698   {NULL, NULL}
 699 };
 700 
 701 static const luaL_Reg rawop_funcs[] = {
 702   // general raw characteristics
 703   {"get_cfa",           rawop_get_cfa},
 704   {"get_cfa_offsets",   rawop_get_cfa_offsets},
 705   {"get_bits_per_pixel",rawop_get_bits_per_pixel},
 706   {"get_raw_neutral",   rawop_get_raw_neutral},
 707   {"get_black_level",   rawop_get_black_level},
 708   {"get_white_level",   rawop_get_white_level},
 709 
 710   // buffer sizes
 711   {"get_raw_width",     rawop_get_raw_width},
 712   {"get_raw_height",    rawop_get_raw_height},
 713   {"get_active_left",   rawop_get_active_left},
 714   {"get_active_top",    rawop_get_active_top},
 715   {"get_active_width",  rawop_get_active_width},
 716   {"get_active_height", rawop_get_active_height},
 717   {"get_jpeg_left",     rawop_get_jpeg_left},
 718   {"get_jpeg_top",      rawop_get_jpeg_top},
 719   {"get_jpeg_width",    rawop_get_jpeg_width},
 720   {"get_jpeg_height",   rawop_get_jpeg_height},
 721 
 722   // raw buffer access
 723   {"get_pixel",         rawop_get_pixel},
 724   {"set_pixel",         rawop_set_pixel},
 725   {"get_pixels_rgbg",   rawop_get_pixels_rgbg},
 726   {"set_pixels_rgbg",   rawop_set_pixels_rgbg},
 727   {"fill_rect",         rawop_fill_rect},
 728   {"meter",             rawop_meter},
 729 
 730   // value conversion
 731   {"raw_to_ev",         rawop_raw_to_ev},
 732   {"ev_to_raw",         rawop_ev_to_raw},
 733 
 734   // histogram
 735   {"create_histogram",  rawop_create_histogram},
 736   {NULL, NULL}
 737 };
 738 
 739 // initialize raw params that may change between frames (currently neutral and related values)
 740 // could update only if changed, but not needed
 741 static void init_raw_params(void) {
 742     // empirical guestimate
 743     // average pixel value of a neutral subject shot with canon AE, as a fraction of usable dynamic range
 744     // found to be reasonably close on d10, elph130, a540, g1x and more.
 745     double raw_neutral_count = (double)(camera_sensor.white_level - camera_sensor.black_level)/(6.669);
 746     log2_raw_neutral_count = log2(raw_neutral_count);
 747     raw_neutral = round_d2i(raw_neutral_count) + camera_sensor.black_level;
 748 }
 749 
 750 // update values that need to be updated when hook becomes active
 751 void rawop_update_hook_status(int active) {
 752     if(active) {
 753         raw_buffer_valid = is_raw_possible();
 754         init_raw_params();
 755     } else {
 756         raw_buffer_valid = 0;
 757     }
 758 }
 759 
 760 int luaopen_rawop(lua_State *L) {
 761     // initialize globals
 762     raw_buffer_valid = 0;
 763 
 764     int i;
 765     int g1=1;
 766     for(i=0; i<4; i++) {
 767         int c = (camera_sensor.cfa_pattern >> 8*i) & 0xFF;
 768         int ci=0;
 769         switch(c) {
 770             case 0:
 771                 ci=0;
 772             break;
 773             case 1:
 774                 if(g1) {
 775                     ci=1;
 776                     g1=0;
 777                 } else {
 778                     ci=2;
 779                 }
 780             break;
 781             case 2:
 782                 ci=3;
 783             break;
 784         }
 785         cfa_offsets[ci][0] = i&1;
 786         cfa_offsets[ci][1] = (i&2)>>1;
 787     }
 788 
 789     // TODO - maybe this should only be done in update_hook_status, since any changeable values
 790     // will only be known at that point.
 791     init_raw_params();
 792 
 793     luaL_newmetatable(L,RAWOP_HISTO_META);
 794     luaL_register(L, NULL, rawop_histo_meta_methods);  
 795     /* use a table of methods for the __index method */
 796     lua_newtable(L);
 797     luaL_register(L, NULL, rawop_histo_methods);  
 798     lua_setfield(L,-2,"__index");
 799     lua_pop(L,1);
 800 
 801     /* global lib*/
 802     lua_newtable(L);
 803     luaL_register(L, "rawop", rawop_funcs);  
 804     return 1;
 805 }

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