Code: Select all
/' -- weighted average blending - 2021 May 9 - by dafhi - works in fbc 1.08 or 7 and earlier
intuition: make 'foreground' with iteration (a simple multiplier)
more natural looking
anti-bonus: slow
updates:
May 9 - removed ulong associates from types sRGB and rgbi
'/
'#include "inc/dsi aadot.bas"
'#include "dsi colorspace.bas"
'#include "dsi util.bas"
'#include "dsi imvars.bas"
'#include "fb 1337 h4x.bas"
#undef int
#define def #define
def int as Integer
def sng as single
def decl declare
def prop property
def oper operator
def csr constructor
def ac as const
#Ifndef flo '' replaces int()
#Define flo(x) (((x)*2.0-0.5)shr 1) '' http://www.freebasic.net/forum/viewtopic.php?p=118633
#define ceil(x) (-((-(x)*2.0-0.5)shr 1))
#EndIf
' -- dsi imvars continued ..
'
type imagevars '2021 May 7 - by dafhi
declare sub get_info( as any ptr = 0 ) '' example: get_info imagecreate(400, 300)
int w,h,bpp,bypp,pitch,rate '' fb standard
as any ptr im, pixels
as string driver_name
sng wh, hh, diagonal '' specialized
int wm, hm, pitchBy
as ulong ptr p32
decl oper cast as any ptr
declare destructor
private:
decl sub _specialized
end type
Destructor.imagevars
If ImageInfo(im) = 0 Then ImageDestroy im: im=0
End Destructor
sub imagevars._specialized
wm = w - 1: wh = w/2
hm = h - 1: hh = h/2
pitchBy = pitch \ bypp
p32 = pixels: diagonal = sqr(w*w + h*h)
End Sub
sub imagevars.get_info( _im as any ptr )
if _im = 0 then ScreenInfo w,h, bpp, bypp, pitch, rate, driver_name: pixels = screenptr: im = 0: _specialized: exit sub
if Imageinfo(_im) = 0 then im = _im: ImageInfo im, w, h, bypp, pitch, pixels: bpp = bypp * 8: _specialized
end sub
oper imagevars.cast as any ptr
return im
end oper
' -- dsi util continued ..
'
def min( a, b) iif( (a)<(b), (a), (b) )
def max( a, b) iif( (a)>(b), (a), (b) )
function clamp( in sng, hi sng = 1, lo sng = 0) sng
return min( max( lo, in), hi)
End Function
' -- dsi colorspace continued ..
'
type sRGB
sng r, g, b
End Type
operator +( l ac sRGB, r ac sRGB) as sRGB: return type( l.r+r.r, l.g+r.g, l.b+r.b): end oper
operator *( l ac sRGB, r sng) as sRGB: return type( r*l.r, r*l.g, r*l.b): end oper
' ------
'' sRGB + iteration component
'
Type rgbi
decl csr
decl csr( sng=0, sng=0, sng=0, sng=0)
decl csr( as sRGB=type(0,0,0), sng=1)
declare operator Cast ac ULong '' as const
as sRGB sum
sng iter
End Type
csr rgbi
end csr
csr rgbi( rr sng, gg sng, bb sng, i sng): sum.r = rr: sum.g = gg: sum.b = bb: iter = i
end csr
csr rgbi( s as sRGB, i sng): sum = s: iter = i
end csr
operator rgbi.Cast ac ulong '' as const
Static sng _mul: _mul = 255.5 / iter
Return RGB( _
clamp( sum.r * _mul, 255.499), _
clamp( sum.g * _mul, 255.499), _
clamp( sum.b * _mul, 255.499) )
End oper
oper +( l ac rgbi, r ac rgbi) ac rgbi: return type<rgbi>( l.sum+r.sum, l.iter+r.iter): end operator
oper +( l ac rgbi, r ac sRGB) ac rgbi: return type<rgbi>( l.sum+r, l.iter+1): end operator
type rgbi_buf
decl prop w int
decl prop h int
decl prop wm int
decl prop hm int
decl sub resize( int, int)
decl sub target( byref as imagevars ptr)
decl sub fill( as sRGB = type(.5,.5,.5), sng = 1)
decl sub draw
as rgbi data(any, any)
private:
as imagevars ptr pTarget
End Type
prop rgbi_buf.w int: return ubound(data,1)+1
end prop
prop rgbi_buf.h int: return ubound(data,2)+1
end prop
prop rgbi_buf.wm int: return ubound(data,1)
end prop
prop rgbi_buf.hm int: return ubound(data,2)
end prop
sub rgbi_buf.target( byref pTarg as imagevars ptr): pTarget = pTarg
if h < 1 andalso pTarg->h > 0 then resize pTarg->w, pTarg->h
End Sub
sub rgbi_buf.resize( ww int, hh int)
redim data( ww-1, hh-1)
End Sub
sub rgbi_buf.fill( col as sRGB, strength sng)
static as rgbi c: c = type(col, strength) ' strength copied to .iter
c.sum *= strength ' match .iter
for y int = 0 to hm
for x int = 0 to wm
data(x,y) = c: Next: Next
End Sub
sub rgbi_buf.draw
dim int x1 = max( wm, pTarget->wm)
for y int = 0 to max( hm, pTarget->hm)
var p = pTarget->p32 + y * pTarget->pitchBy
for x int = 0 to x1
p[x] = data(x, y)
'pset *pTarget, (x,y), data(x, y)
Next: Next
End Sub
' -- dsi aadot continued ..
'
namespace AaDot_noSq '2021 May 8 - by dafhi
dim as rgbi_buf ptr pTarget
dim sng clip_x0, clip_y0, clip_x1, clip_y1
sub clipper( x sng = 0, y sng = 0, w sng = 0, h sng = 0)
if w<=0 then w = pTarget->w
if h<=0 then h = pTarget->h
clip_x0 = iif( x < 0, 0, x): x += w
clip_y0 = iif( y < 0, 0, y): y += h
clip_x1 = iif( x < pTarget->w-.5, x, pTarget->w-.5001)
clip_y1 = iif( y < pTarget->h-.5, y, pTarget->h-.5001)
end sub
sub render_target( byref pTarg as rgbi_buf ptr): pTarget = pTarg
clipper
end sub
dim sng dy,dxLeft,salpha,cone_h,coneSq,sq,slope
dim int x0,y0,x1,y1
sub draw( x as single, y as single, col as rgbi, rad sng = .7071, slope sng = 1)
y0=(y-rad): if y0<clip_y0 then y0=clip_y0
y1=(y+rad): if y1>clip_y1 then y1=clip_y1
x0=(x-rad): x0+=(x0-clip_x0)*(x0<clip_x0)
x1=(x+rad): x1+=(x1-clip_x1)*(x1>clip_x1)
static as rgbi col_mul: col_mul = type(col.sum * col.iter, col.iter)
cone_h = slope*(rad+.5) '' i forget
coneSq = cone_h*cone_h
sq = (cone_h-1)*(cone_h-1)
static sng reciprocal_alpha: reciprocal_alpha = col.iter / (coneSq - sq)
dy = (y0-y)*slope: dxLeft = (x0-x)*slope
for y int = y0 to y1
static sng dx, dySq: dx=dxleft: dySq=dy*dy
for x int = x0 to x1
salpha = dx*dx+dySq
if salpha < sq then
pTarget->data(x, y) += col_mul
elseif salpha < coneSq then
salpha = ((coneSq - salpha) * reciprocal_alpha)
pTarget->data(x, y).iter += salpha
pTarget->data(x, y).sum += col.sum * salpha
endif: dx += slope
next: dy += slope
next
end sub
end namespace
type anim_vars
as rgbi col
sng x, y
sng rad
sng slope
sng offrad, angle, ia
End Type
const tau = 8 * atn(1)
sub random_vals( a() as anim_vars, buf as imagevars)
var u = -1, base_rad = 30
for i int = 1 to 250
u += 1: redim preserve a(u)
with a(u)
def rm5 3.0 * (rnd - .5)
.col = type<rgbi>(rm5, rm5, rm5, 1 * (.25 + rnd))
.x = rnd * buf.w
.y = rnd * buf.h
.rad = 3 * base_rad * (rnd*rnd*rnd + .02)
.slope = .6 + rnd*.2 '' 0.5 sharp .. 1.0 smooth
.offrad = .1 * buf.diagonal * (.33 + rnd)
.angle = rnd * tau
.ia = .025 * (rnd - .5)
End With
next
End Sub
sub draw_frame( a() as anim_vars, _buf as rgbi_buf)
_buf.fill type(.81,.79,.77), .4
for i int = 0 to ubound(a)
with a(i)
AaDot_noSq.draw _
.x + .offrad * cos(.angle), _
.y + .offrad * sin(.angle), _
.col, .rad, .slope / .rad
.angle += .ia
end with
next
end sub
screenres 800, 600, 32
dim as imagevars buf
buf.get_info '' grab screen
dim as rgbi_buf _buf
_buf.target @buf '' call after buf has acquired data
AaDot_noSq.render_target @_buf
dim as anim_vars a()
random_vals a(), buf
for frame int = 1 to 440
draw_frame a(), _buf
screenlock
_buf.draw
screenunlock
if inkey = chr(27) then exit for
sleep 1
next
? "demo finished. exiting .."
sleep 1000 * 6