weighted summation blending

Post your FreeBASIC source, examples, tips and tricks here. Please don’t post code without including an explanation.
Post Reply
dafhi
Posts: 1640
Joined: Jun 04, 2005 9:51

weighted summation blending

Post by dafhi »

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
Post Reply