gen2 accumulator. forget ushort .. i'm using a ubyte

Code: Select all

```
#define dbl as double '' reduced text
#define sng as single
#define min( a, b) iif( (a)<(b), (a), (b) )
#define max( a, b) iif( (a)>(b), (a), (b) )
#macro sw( a, b, tmp )
tmp = a: a = b: b = tmp
#endmacro
function modu( in as double, m as double = 1 ) as double
return in - m * int( in / m )
end function
function round(in as double, places as ubyte = 2) as string
dim as integer mul = 10 ^ places
return str(csng( int(in * mul + .5) / mul) )
End Function
Union uARGB
As Ulong col
Type: As UByte B,G,R,A
End Type
declare constructor( as ulong = 0 )
declare operator cast as string
declare operator cast as ulong
declare operator let( as ulong)
End Union
constructor uARGB( in as ulong )
col = in
end constructor
operator uARGB.let( in as ulong )
r = (in shr 16) and 255
g = (in shr 8) and 255
b = in and 255
end operator
operator uARGB.cast as string
return str(r) + " " + str(g) + " " + str(b)
end operator
operator uARGB.cast as ulong
return col
end operator
dim shared as ulong ptr p32
dim shared as long wm, hm, pitchBy
sub _gfx_release( byref im as any ptr )
if imageinfo(im) = 0 then imagedestroy im
im = 0
end sub
const tau = 8*atn(1)
'' image class
''
type t_image_info
dim as long w,h, bypp, pitch,rate
dim as any ptr pixels, im
dim as string driver_name
declare sub get_info( as any ptr = 0 )
end type
sub _get_screen( byref i as t_image_info )
_gfx_release i.im
ScreenInfo i.w, i.h, , i.bypp, i.pitch, i.rate, i.driver_name
i.pixels = screenptr
end sub
sub _get_image( byref i as t_image_info, im as any ptr )
if im<>i.im then _gfx_release i.im '' 2024 June 3
ImageInfo im, i.w, i.h, i.bypp, i.pitch, i.pixels
i.im = im
end sub
sub t_image_info.get_info( im as any ptr )
if im = 0 then _get_screen this: exit sub
_get_image this, im
end sub
namespace line2d '' rasterizer 2024 June 15 by dafhi
/'
example: screenres 800,600,32
myline.render_target 0
myline.draw rnd*800,rnd*600,rnd*800,rnd*600, rgba(255,255,255,50)
'/
dim as t_image_info im
sub render_target( _i as any ptr )
im.get_info _i
pitchBy = im.pitch \ 4 '' integer divide
p32 = im.pixels
wm = im.w - 1
hm = im.h - 1
end sub
function _no_intersect( byref x sng, byref y sng, byref x1 sng, byref y1 sng, slope sng, _max sng, _min sng = 0 ) as long
static sng ptr xmin, xmax, ymin, ymax, xmin_y, xmax_y, ymin_x, ymax_x
if x1 < x then
xmin = @x1: xmax = @x
xmin_y = @y1: xmax_y = @y
else
xmin = @x: xmax = @x1
xmin_y = @y: xmax_y = @y1
endif
dim as long retval = *xmin >= _max orelse *xmax < _min
if *xmin < _min then
*xmin_y += (_min - *xmin) * slope
*xmin = _min
endif
_max -= .0001
if *xmax > _max then
*xmax_y -= (*xmax - _max) * slope
*xmax = _max
endif
return retval
end function
sub _make_unrenderable( byref x sng, byref x1 sng )
x = 1
x1 = 0
end sub
type t_returns
sng ptr px,py
sng x,y, _x, _y, x1, slope
end type
dim as t_returns ret
dim sng slope, s_temp, dx, dy
sub _absdxdy_sorted( byref x sng, byref y sng, byref x1 sng, byref y1 sng, byref px sng, byref py sng, _im_w sng, _im_h sng, border_test sng = 10 )
if x > x1 then
sw( x, x1, s_temp )
sw( y, y1, s_temp )
endif
dx = x1 - x
dy = y1 - y: slope = dy / dx
if _no_intersect( x,y, x1,y1, slope, _im_w-border_test, border_test ) then _make_unrenderable ret._x, ret.x1: exit sub
if _no_intersect( y,x, y1,x1, dx/dy, _im_h-border_test, border_test ) then _make_unrenderable ret._x, ret.x1: exit sub
ret._x = x - .4999
ret._y = y - .4999
ret.x1 = x1 - .4999
ret.slope = slope
end sub
sub _common( byref x sng, byref y sng, byref x1 sng, byref y1 sng )
const sng border_test = 0.0'113 '' .022 crashes .. 023 might :P
if abs(y1 - y) > abs(x1 - x) then
ret.px = @ret.y: ret.py = @ret.x
_absdxdy_sorted y, x, y1, x1, x,y, im.h, im.w, border_test
else
ret.px = @ret.x: ret.py = @ret.y
_absdxdy_sorted x, y, x1, y1, x,y, im.w, im.h, border_test
endif
end sub
#define line2d_loopS _common x, y, x1, y1: ret.x=ret._x: ret.y=ret._y: while ret.x < ret.x1: _
if *ret.px > -0.5 andalso *ret.py > -0.5 andalso _
*ret.px < (wm+.5) andalso *ret.py < (hm+.5) then
#define line2d_loopE endif: ret.y += ret.slope: ret.x += 1: wend
sub draw( x sng, y sng, x1 sng, y1 sng, col as ulong)
line2d_loopS
' ppset *ret.px, *ret.py, col
line2d_loopE
end sub
end namespace
namespace roll_accum '' 2024 June 15 by dafhi
dim as single _max = 255
dim as single _min = 0
type accum_int as ubyte
const lenx8 = len(accum_int) * 8
const adj_ = max(1, lenx8 / 16)
const cb_sum = lenx8 \ 2 + adj_
const cb_c = lenx8 - cb_sum
const as single cb_v = 2^(cb_sum - adj_) \ 2^(cb_c) 'iif(0, 1, lenx8 - 2 * cb_c)
const c_mag = 2 ^ cb_c, v_mag = 2 ^ cb_v, sum_mag = 2 ^ (lenx8 - cb_c)
dim as single _scale_in, _scale_out
sub set_range( ma sng = 255, mi sng = 0 )
_max = ma: _min = mi
_scale_in = (v_mag - 0) / ((ma - mi))
_scale_out = 1 / _scale_in
end sub
const c_shl = lenx8 - cb_c
function fc( i as accum_int) as accum_int
return i shr c_shl
end function
function readv( i as accum_int ) as single
return _min + _scale_out * (i and (sum_mag - 1)) / fc(i)
end function
sub addv( byref des as accum_int, f as single )
if des > 0 then: static as ushort c, i
f = (f - _min) * _scale_in + (des and (sum_mag - 1))
c = fc(des)
if c = (c_mag-1) then
f /= (c + 1)
i = c_mag - 1
f *= i
else
i = c + 1
endif
des = (i shl c_shl) or (f and (sum_mag-1))
'? tab(1); iif(rollover,"*", ""); round(v);" ";c+1;" "; round(s_new_val); " ";
else '' des = 0 [uninitialized]
set_range _max, _min
des = (1 shl c_shl) or (f - _min) * _scale_in
endif
end sub
end namespace ' -- roll_accum
namespace radon_test '' 2024 June 15 - by dafhi
dim as t_image_info source
using roll_accum
type cRGB
as accum_int r,g,b
declare sub vals( as ubyte, as ubyte, as ubyte )
declare sub reset
declare operator cast as ulong
end type
sub cRGB.reset
r = 0: g = 0: b = 0
end sub
sub cRGB.vals( rr as ubyte, gg as ubyte, bb as ubyte )
reset
addv r, rr
addv g, gg
addv b, bb
end sub
operator cRGB.cast as ulong
return rgb( roll_accum.readv(r), roll_accum.readv(g), roll_accum.readv(b))
end operator
dim as cRGB accRGB(), raycol
'dim as cRGB backup_scan()
sub _encode_initialize( im as any ptr )
source.get_info im
wm = source.w-1
hm = source.h-1
redim accRGB( wm, hm )
line2d.render_target imagecreate( source.w, source.h, rgb(0,0,0) )
'redim backup_scan( max( wm, hm ) )
end sub
sub _cRGB_to_im
for y as long = 0 to hm
for x as long = 0 to wm
dim byref as cRGB q = accRGB( x,y )
p32[y*pitchBy + x] = rgb( readv(q.r), readv(q.g), readv(q.b) )
next
next
end sub
sub shoot_xray( x sng, y sng, x1 sng, y1 sng ): using line2d
raycol.reset
dim as uargb ptr a = source.pixels
line2d_loopS
dim as long i = *ret.px + clng(*ret.py) * pitchBy
roll_accum.addv raycol.r, a[ i ].r
roll_accum.addv raycol.g, a[ i ].g
roll_accum.addv raycol.b, a[ i ].b
line2d_loopE
end sub
sub _line_accum( x sng, y sng, x1 sng, y1 sng, c as ulong ): using line2d
#if 0
line line2d.im.im, (x,y)-(x1,y1),c
#else
line2d_loopS
dim as uargb uar = c
dim byref as cRGB q = accRGB( *ret.px, *ret.py )
roll_accum.addv q.r, uar.r
roll_accum.addv q.g, uar.g
roll_accum.addv q.b, uar.b
line2d_loopE
#endif
end sub
sub process( im as any ptr )
_encode_initialize im
dim as long c_pixels = source.w * source.h
dim as single diagonal = sqr( source.w^2 + source.h^2)
for i_line as long = 1 to 4999
dim as single si = rnd*c_pixels
dim as single y = si / source.w
dim as single x = si - int(y) * source.w
dim as single a = rnd * tau
dim as single slen = diagonal'sqr(diagonal) + rnd * diagonal / 3
dim as single x1 = x + slen * cos(a): x -= slen * cos(a)
dim as single y1 = y + slen * sin(a): y -= slen * sin(a)
shoot_xray x,y,x1,y1
_line_accum x,y,x1,y1, raycol
next
_cRGB_to_im
put (source.w,0), line2d.im.im, pset
end sub
end namespace ' -- radon_test
screenres 800,600, 32
dim as t_image_info buf
buf.get_info
dim as any ptr im = imagecreate( buf.w/2, buf.h, iif(1, rgb(255,255,255), 0) )
randomize 7
for i as long = 0 to 9
circle im, (rnd * buf.w/2, rnd * buf.h), 4 + rnd * 50, rgb(0,rnd*255,0),,,,f
' circle im, (rnd * buf.w/2, rnd * buf.h), 4 + rnd * 50, rnd * culng(-1),,,,f
next
put (0,0), im, pset
radon_test.process im
sleep
```