Here's the enhancements to rawop_meter I mentioned, along with a test script.
static int rawop_meter(lua_State *L) {
if(!raw_buffer_valid) {
return luaL_error(L,"raw data not available");
}
unsigned x1=luaL_checknumber(L,1);
unsigned y1=luaL_checknumber(L,2);
unsigned x_count=luaL_checknumber(L,3);
unsigned y_count=luaL_checknumber(L,4);
unsigned x_step=luaL_checknumber(L,5);
unsigned y_step=luaL_checknumber(L,6);
// no pixels
if(!x_count || !y_count) {
return 0;
}
unsigned x_max = x1 + x_step * x_count;
unsigned y_max = y1 + y_step * y_count;
// x out of range
if(x_max > (unsigned)camera_sensor.raw_rowpix) {
return 0;
}
// y out of range
if(y_max > (unsigned)camera_sensor.raw_rows) {
return 0;
}
//lapser - max value is 2^63 now, so overflow check not needed
// overflow possible (int max)/total < max value
// if(x_count*y_count > (unsigned)0xFFFFFFFF >> camera_sensor.bits_per_pixel) {
// return 0;
// }
unsigned x,y;
int t=0; //int detects overflow into sign bit when t<0 (lapser)
unsigned t1=0; //overflow counter
unsigned p,pmax1=0,pmax2=0,nwhite=0; //lapser variables for ETTR use
for(y = y1; y < y_max; y += y_step) {
for(x = x1; x < x_max; x += x_step) {
//t+=get_raw_pixel(x,y);
p=get_raw_pixel(x,y); //lapser
//set_raw_pixel(x,y,(short)camera_sensor.white_level); //*****TEST*****
if(p>=pmax2) { //must use >=, not >, for nwhite counting
if(p>=camera_sensor.white_level)nwhite++;
if(p>pmax1) { //finds brightest and 2nd brightest pixels for ETTR
pmax2=pmax1;
pmax1=p;
}
else pmax2=p;
}
t+=p;
if(t<0){ //handles overflow
t1++;
t &= 0x7FFFFFFF;
}
}
}
x=x_count*y_count;
y = ((unsigned)t | (t1<<31)); //can use unsigned bit 31 now
t1 >>= 1; // [t1,y] is now a 64 bit integer
while(t1!=0){
y = (y>>1) | (t1<<31); // 64 bit right shift >> 1
t1 >>= 1;
x >>= 1; //shift denominator so y/x value is unchanged
}
lua_pushnumber(L,y/x);
lua_pushnumber(L,pmax2); //lapser
lua_pushnumber(L,nwhite); //lapser
lua_pushnumber(L,pmax1); //lapser
//return 1;
return 4; //lapser
}
And here's a script to test them with:
--[[
@title Lapser Rawop Test
@chdk_version 1.5.0
#nshots=4 "# Shots (0: no limit)"
#otest=false "Overflow Test?"
]]
--logger s: one line sent to log file (set fname before first call)
bi=get_buildinfo()
fname="A/CHDK/LOGS/"..bi.platform..os.date("_%y%m%d_%H%M_TestRwop.log")
function logger(s)
if slog==nil then -- first call opens file
if s==nil then return end -- don't open empty file
flog=io.open(fname,"ab")
slog={}
nlog=0
end
if s~=nil then
nlog=nlog+1
slog[nlog]=s
else
for i=1,nlog do
flog:write(slog[i],"\n")
end
flog:close()
slog=nil
end
end
function ksleep(t)
wait_click(t)
if is_key("menu") or is_pressed("menu") then done=true end
end
function mparms(maxsteps,px1,py1,px2,py2)
logger(string.format("maxsteps=%d,px1=%d,py1=%d,px2=%d,py2=%d",maxsteps,px1,py1,px2,py2 ))
local jwh=rawop.get_jpeg_width()
local jlt=rawop.get_jpeg_left()
px1=jlt+((px1*jwh)/100)
px2=jlt+((px2*jwh)/100)-px1 -- px2 is width now
jwh=rawop.get_jpeg_height()
jlt=rawop.get_jpeg_top()
py1=jlt+((py1*jwh)/100)
py2=jlt+((py2*jwh)/100)-py1 -- py2 is height now
logger(string.format("x=%d,y=%d,w=%d,h=%d",px1,py1,px2,py2 ))
local step=1
while(px2*py2)/(step*step)>maxsteps do step=step+2 end
local xsteps=px2/step + 1
local ysteps=py2/step + 1
px1=px1+((px2%step)/2) -- center sampled area
py1=py1+((py2%step)/2)
logger(string.format("x=%d,y=%d,xsteps=%d,ysteps=%d,step=%d",
px1,py1,xsteps,ysteps,step))
return px1,py1,xsteps,ysteps,step
end
--bi=get_buildinfo()
logger("TestRwop "..os.date())
logger(string.format("Camera:%s f/w:%s platformID:%s bit/pixel:%d",
bi.platform,bi.platsub,bi.platformid,rawop.get_bits_per_pixel()))
logger(string.format("version:%s %s built on %s %s",
bi.version,bi.build_number,bi.build_date,bi.build_time))
logger(string.format("Nshots=%d",nshots))
cls()
--set_console_autoredraw(-1)
set_draw_title_line(0)
osd=get_config_value(1)
set_config_value(1, 0)
done=false
hook_raw.set(10000000)
if otest then msteps=24000000 else msteps=24000 end -- overflow test?
mx1,my1,mxcount,mycount,mxystep=mparms(msteps,0,0,100,100)
nsteps=mxcount*mycount
white=rawop.get_white_level()
logger(string.format("nsteps=%d white=%d",nsteps,white))
logger("Shot# Mean Pmax2 Pmax1 Wh% Wh#")
logger() -- write log so far
press("shoot_half")
repeat sleep(10) until get_shooting()
press("shoot_full_only")
ishots=0
repeat
while not hook_raw.is_ready() do ksleep(10) end
ishots=ishots+1
mean,pmax2,nwhite,pmax1=rawop.meter(mx1,my1,mxcount,mycount,mxystep,mxystep)
logger(string.format("%5d%6d%6d%6d%3d%% %d",
ishots,mean,pmax2,pmax1,(nwhite*100)/nsteps, nwhite))
if done or ishots==nshots then
release("shoot_full")
done=true
end
hook_raw.continue()
until done
logger() -- print log and close file
set_config_value(1,osd)
To compile a test build, just put the attached rawhookops.c in the modules folder, replacing the one that's already there.
To run the test script, also attached, put the camera in continuous mode first, set the parameter for the number of shots you want, and if you want to do an overflow test. The overflow test sets the step size to 1, so it takes awhile between shots. For overflow testing, you can use manual exposure, 1 second, ISO 128000 to get a mostly white image.
The script creates a log file that looks like this (with overflow testing)
TestRwop Thu Sep 7 16:05:22 2017
Camera:g1x f/w:100g platformID:12851 bit/pixel:14
version:CHDK 1.5.0 built on Sep 7 2017 15:51:16
Nshots=0
maxsteps=24000000,px1=0,py1=0,px2=100,py2=100
x=108,y=76,w=4352,h=3264
x=108,y=76,xsteps=4353,ysteps=3265,step=1
nsteps=14212545 white=16383
Shot# Mean Pmax2 Pmax1 Wh% Wh#
1 16382 16383 16383 99% 14207056
2 16382 16383 16383 99% 14206049
3 12118 16383 16383 34% 4852188
4 12008 16383 16383 34% 4939794
5 11400 16383 16383 27% 3936243
6 10838 16383 16383 25% 3610153
7 10994 16383 16383 31% 4544427
Press and hold the menu button to exit the program (or set the number of shots>0)
[EDIT] I updated the attached TestRwop.lua to work with the EOS-M3