It is currently Wed May 22, 2013 9:20 am

All times are UTC + 1 hour




Post new topic Reply to topic  [ 6 posts ] 
Author Message
 Post subject: class for image manipulation (OOP)
PostPosted: Fri Apr 13, 2012 6:33 pm 
Offline
User
User
User avatar

Joined: Sat May 22, 2004 1:38 am
Posts: 69
Here is some 2 years old code of me for someone who may has better use of :?
And because of the error I got at the first try posting it here (Your message contains 82945 characters. The maximum number of allowed characters is 60000.) it is split in 2 parts.
Part 1/2:
Code:
Interface IImageFilter ;generates a new image id
;- public
 ;getter
  getImage()
  getWidth()
  getHeight()
  getPixelCount()
  getImageMem()
 ;image information
  getAverage.f(channel.i = -1)
  getStandardDeviation.f(channel.i = -1)
  getCenterOfMassX.f(channel.i = -1)
  getCenterOfMassY.f(channel.i = -1)
  getSemimajorAxisAngle.f(channel.i = -1)
  getExcentricity.f(channel.i = -1)
 ;color
  grayscale()
  invert()
  brightness(delta.i)
  contrast(factor.f)
  colorScale(factor.f = 1, delta.i = 0)
  gamma(g.f)
  normalize()
 ;transform
  mirrorVertical()
  mirrorHorizontal()
  rotate(angle.f, nonBilinear.i = #False, resize.i = #False)
  resize(newWidth.i, newHeight.i, mode.i)
 ;overlay
  add_(image.i, factor.f = 1, delta.i = 0)
  sub_(image.i, factor.f = 1, delta.i = 0)
  mul_(image.i, factor.f = 1, delta.i = 0)
  div_(image.i, factor.f = 1, delta.i = 0)
  xor_(image.i)
  and_(image.i)
  or_(image.i)
  weight(image.i, factor.f = 1, delta.i = 0)
  weightMask(image.i, mask.i, factor.f = 1, delta.i = 0)
  difference(image.i, factor.f = 1, delta.i = 0)
  euclidianNorm(image.i, offset.i)
  manhattenNorm(image.i, offset.i)
  addColorOverlay(color.i, opacity.f)
  removeColorOverlay(color.i, opacity.f)
 ;denoise
  median(size.i)
  nearMedian(normalSize.i, nearSize.i)
  binomial(size.i)
 ;edge detection
  minMax(size.i)
  DoG(q.i, p.i)
  houghTransformation(threshold.i)
 ;segmenting
  threshold(value.i, keepColor.i = #False) ;grayscale
  regionGrowing(x.i, y.i, maxDelta.i) ;H3, grayscale
 ;morphology
  dilate(label.i, mask$, times.i) ;segmented
  erode(label.i, mask$, times.i) ;segmented
  closing(label.i, mask$, times.i) ;segmented
  opening(label.i, mask$, times.i) ;segmented
  thin(label.i, times.i) ;segmented
  skeletonization(label.i) ;segmented
 ;others
  generic(filter$)
  bswap()
 ;call after filtering to update the source image
  output()
 ;free object
  delete()
;- private
  getColorArray()
  setColorArray(*mem)
  memBinomial(*mem, size.i)
  memGeneric(*mem, filter$)
EndInterface

;mask$:
; |   separates rows
; ,   separates columns
; first columns, then rows
; example: 0,1,0|1,1,1|0,1,0

;filter$
; |   separates rows
; ,   separates columns
; ;   separates parameters
; first columns, then rows
; first filter matrix, then divisor, then offset
; example: 1,2,1|2,4,2|1,2,1;16;0

Structure OImageFilter
 ;Address to the methods array
 methodAddress.i
 ;Class Attributes
  image.i
  width.i
  height.i
  pixels.i
  srcMem.i
EndStructure

Structure ImageFilter_RGBA
 StructureUnion
  rgba.l
  channel.b[4]
 EndStructureUnion
EndStructure

Structure ImageFilter_GrayPosition
 gray.i
 x.i
 y.i
EndStructure


#IF_UsedChannels = 4

CompilerIf #IF_UsedChannels = 4
 #IF_ImageDepth = 32
CompilerElse
 #IF_ImageDepth = 24
CompilerEndIf

Enumeration ;resize modes
 #IF_RM_NearestNeighbor
 #IF_RM_Bilinear ;not implemented yet
 #IF_RM_Bicubic ;not implemented yet
 #IF_RM_Spline ;not implemented yet
 #IF_RM_Lanczos ;not implemented yet
 #IF_RM_FFT ;not implemented yet
EndEnumeration


Macro getColorFromArray(addr, x, y, width)
 PeekL((addr) + (((y) * (width)) + (x)) * SizeOf(ImageFilter_RGBA))
EndMacro

Macro setColorFromArray(addr, x, y, width, color)
 PokeL((addr) + (((y) * (width)) + (x)) * SizeOf(ImageFilter_RGBA), (color))
EndMacro

Macro limit(var, l, u)
 If (var) < (l) : var = l : EndIf
 If (var) > (u) : var = u : EndIf
EndMacro

Macro Square(number)
 ((number) * (number))
EndMacro

Macro Gray(rgb)
 Round((Red(rgb) * 0.299) + (Green(rgb) * 0.587) + (Blue(rgb) * 0.114), #PB_Round_Nearest)
EndMacro

Macro MeanGray(rgb)
 Round((Red(rgb) + Green(rgb) + Blue(rgb)) / 3, #PB_Round_Nearest)
EndMacro

Macro Sgd(x)
 (1 / (1 + Pow(2.718281828459045, -(x))))
EndMacro


;public
Declare.i newImageFilter(Image.i)
Declare.i ImageFilter_getImage(*this.IImageFilter)
Declare.i ImageFilter_getWidth(*this.IImageFilter)
Declare.i ImageFilter_getHeight(*this.IImageFilter)
Declare.i ImageFilter_getPixelCount(*this.IImageFilter)
Declare.i ImageFilter_getImageMem(*this.IImageFilter)
Declare.f ImageFilter_getAverage(*this.IImageFilter, channel.i = -1)
Declare.f ImageFilter_getStandardDeviation(*this.IImageFilter, channel.i = -1)
Declare.f ImageFilter_getCenterOfMassX(*this.IImageFilter, channel.i = -1)
Declare.f ImageFilter_getCenterOfMassY(*this.IImageFilter, channel.i = -1)
Declare.f ImageFilter_getSemimajorAxisAngle(*this.IImageFilter, channel.i = -1)
Declare.f ImageFilter_getExcentricity(*this.IImageFilter, channel.i = -1)
Declare.i ImageFilter_grayscale(*this.IImageFilter)
Declare.i ImageFilter_invert(*this.IImageFilter)
Declare.i ImageFilter_brightness(*this.IImageFilter, delta.i)
Declare.i ImageFilter_contrast(*this.IImageFilter, factor.f)
Declare.i ImageFilter_colorScale(*this.IImageFilter, factor.f = 1, delta.i = 0)
Declare.i ImageFilter_gamma(*this.IImageFilter, g.f)
Declare.i ImageFilter_normalize(*this.IImageFilter)
Declare.i ImageFilter_mirrorVertical(*this.IImageFilter)
Declare.i ImageFilter_mirrorHorizontal(*this.IImageFilter)
Declare.i ImageFilter_rotate(*this.IImageFilter, angle.f, nonBilinear.i = #False, resize.i = #False)
Declare.i ImageFilter_resize(*this.IImageFilter, newWidth.i, newHeight.i, mode.i)
Declare.i ImageFilter_add(*this.IImageFilter, *image.IImageFilter, factor.f = 1, delta.i = 0)
Declare.i ImageFilter_sub(*this.IImageFilter, *image.IImageFilter, factor.f = 1, delta.i = 0)
Declare.i ImageFilter_mul(*this.IImageFilter, *image.IImageFilter, factor.f = 1, delta.i = 0)
Declare.i ImageFilter_div(*this.IImageFilter, *image.IImageFilter, factor.f = 1, delta.i = 0)
Declare.i ImageFilter_xor(*this.IImageFilter, *image.IImageFilter)
Declare.i ImageFilter_and(*this.IImageFilter, *image.IImageFilter)
Declare.i ImageFilter_or(*this.IImageFilter, *image.IImageFilter)
Declare.i ImageFilter_weight(*this.IImageFilter, *image.IImageFilter, factor.f = 1, delta.i = 0)
Declare.i ImageFilter_weightMask(*this.IImageFilter, *image.IImageFilter, *mask.IImageFilter, factor.f = 1, delta.i = 0)
Declare.i ImageFilter_difference(*this.IImageFilter, *image.IImageFilter, factor.f = 1, delta.i = 0)
Declare.i ImageFilter_euclidianNorm(*this.IImageFilter, *image.IImageFilter, offset.i)
Declare.i ImageFilter_manhattenNorm(*this.IImageFilter, *image.IImageFilter, offset.i)
Declare.i ImageFilter_addColorOverlay(*this.IImageFilter, color.i, opacity.f)
Declare.i ImageFilter_removeColorOverlay(*this.IImageFilter, color.i, opacity.f)
Declare.i ImageFilter_median(*this.IImageFilter, size.i)
Declare.i ImageFilter_nearMedian(*this.IImageFilter, normalSize.i, nearSize.i)
Declare.i ImageFilter_binomial(*this.IImageFilter, size.i)
Declare.i ImageFilter_minMax(*this.IImageFilter, size.i)
Declare.i ImageFilter_DoG(*this.IImageFilter, q.i, p.i)
Declare.i ImageFilter_houghTransformation(*this.IImageFilter, threshold.i)
Declare.i ImageFilter_threshold(*this.IImageFilter, value.i, keepColor.i = #False)
Declare.i ImageFilter_regionGrowing(*this.IImageFilter, x.i, y.i, maxDelta.i)
Declare.i ImageFilter_dilate(*this.IImageFilter, label.i, mask$, times.i)
Declare.i ImageFilter_erode(*this.IImageFilter, label.i, mask$, times.i)
Declare.i ImageFilter_closing(*this.IImageFilter, label.i, mask$, times.i)
Declare.i ImageFilter_opening(*this.IImageFilter, label.i, mask$, times.i)
Declare.i ImageFilter_thin(*this.IImageFilter, label.i, times.i)
Declare.i ImageFilter_skeletonization(*this.IImageFilter, label.i)
Declare.i ImageFilter_generic(*this.IImageFilter, filter$)
Declare.i ImageFilter_bswap(*this.IImageFilter)
Declare.i ImageFilter_output(*this.IImageFilter)
Declare   ImageFilter_delete(*this.IImageFilter)
;private
Declare.i ImageFilter_getColorArray(*this.IImageFilter)
Declare.i ImageFilter_setColorArray(*this.IImageFilter, *mem.ImageFilter_RGBA)
Declare.i ImageFilter_memBinomial(*this.IImageFilter, *mem.ImageFilter_RGBA, size.i)
Declare.i ImageFilter_memGeneric(*this.IImageFilter, *mem.ImageFilter_RGBA, filter$)


DataSection
 OImageFilter_methods:
  Data.i @ImageFilter_getImage()
  Data.i @ImageFilter_getWidth()
  Data.i @ImageFilter_getHeight()
  Data.i @ImageFilter_getPixelCount()
  Data.i @ImageFilter_getImageMem()
  Data.i @ImageFilter_getAverage()
  Data.i @ImageFilter_getStandardDeviation()
  Data.i @ImageFilter_getCenterOfMassX()
  Data.i @ImageFilter_getCenterOfMassY()
  Data.i @ImageFilter_getSemimajorAxisAngle()
  Data.i @ImageFilter_getExcentricity()
  Data.i @ImageFilter_grayscale()
  Data.i @ImageFilter_invert()
  Data.i @ImageFilter_brightness()
  Data.i @ImageFilter_contrast()
  Data.i @ImageFilter_colorScale()
  Data.i @ImageFilter_gamma()
  Data.i @ImageFilter_normalize()
  Data.i @ImageFilter_mirrorVertical()
  Data.i @ImageFilter_mirrorHorizontal()
  Data.i @ImageFilter_rotate()
  Data.i @ImageFilter_resize()
  Data.i @ImageFilter_add()
  Data.i @ImageFilter_sub()
  Data.i @ImageFilter_mul()
  Data.i @ImageFilter_div()
  Data.i @ImageFilter_xor()
  Data.i @ImageFilter_and()
  Data.i @ImageFilter_or()
  Data.i @ImageFilter_weight()
  Data.i @ImageFilter_weightMask()
  Data.i @ImageFilter_difference()
  Data.i @ImageFilter_euclidianNorm()
  Data.i @ImageFilter_manhattenNorm()
  Data.i @ImageFilter_addColorOverlay()
  Data.i @ImageFilter_removeColorOverlay()
  Data.i @ImageFilter_median()
  Data.i @ImageFilter_nearMedian()
  Data.i @ImageFilter_binomial()
  Data.i @ImageFilter_minMax()
  Data.i @ImageFilter_DoG()
  Data.i @ImageFilter_houghTransformation()
  Data.i @ImageFilter_threshold()
  Data.i @ImageFilter_regionGrowing()
  Data.i @ImageFilter_dilate()
  Data.i @ImageFilter_erode()
  Data.i @ImageFilter_closing()
  Data.i @ImageFilter_opening()
  Data.i @ImageFilter_thin()
  Data.i @ImageFilter_skeletonization()
  Data.i @ImageFilter_generic()
  Data.i @ImageFilter_bswap()
  Data.i @ImageFilter_output()
  Data.i @ImageFilter_delete()
  Data.i @ImageFilter_getColorArray()
  Data.i @ImageFilter_setColorArray()
  Data.i @ImageFilter_memBinomial()
  Data.i @ImageFilter_memGeneric()
EndDataSection


Procedure.i newImageFilter(Image.i)
 Protected *object.OImageFilter
 If IsImage(Image) = #Null
  ProcedureReturn #Null
 EndIf
 *object = AllocateMemory(SizeOf(OImageFilter))
 If *object = #Null
  ProcedureReturn #Null
 EndIf
 *object\methodAddress = ?OImageFilter_methods
 *object\image = Image
 *object\width = ImageWidth(Image)
 *object\height = ImageHeight(Image)
 *object\pixels = *object\width * *object\height
 *object\srcMem = ImageFilter_getColorArray(*object)
 *object\image = CreateImage(#PB_Any, *object\width, *object\height, #IF_ImageDepth)
 FreeImage(Image)
 If *object\srcMem = #Null
  FreeMemory(*object)
  ProcedureReturn #Null
 EndIf
 ProcedureReturn *object
EndProcedure


Procedure.i ImageFilter_getImage(*this.IImageFilter)
 Protected *object.OImageFilter
 If *this = #Null
  ProcedureReturn 0
 EndIf
 *object = *this
 ProcedureReturn *object\image
EndProcedure


Procedure.i ImageFilter_getWidth(*this.IImageFilter)
 Protected *object.OImageFilter
 If *this = #Null
  ProcedureReturn 0
 EndIf
 *object = *this
 ProcedureReturn *object\width
EndProcedure


Procedure.i ImageFilter_getHeight(*this.IImageFilter)
 Protected *object.OImageFilter
 If *this = #Null
  ProcedureReturn 0
 EndIf
 *object = *this
 ProcedureReturn *object\height
EndProcedure


Procedure.i ImageFilter_getPixelCount(*this.IImageFilter)
 Protected *object.OImageFilter
 If *this = #Null
  ProcedureReturn 0
 EndIf
 *object = *this
 ProcedureReturn *object\pixels
EndProcedure


Procedure.i ImageFilter_getImageMem(*this.IImageFilter)
 Protected *object.OImageFilter
 If *this = #Null
  ProcedureReturn #Null
 EndIf
 *object = *this
 ProcedureReturn *object\srcMem
EndProcedure


Procedure.f ImageFilter_getAverage(*this.IImageFilter, channel.i = -1)
 Protected *object.OImageFilter, *src.ImageFilter_RGBA, int.i, sum.q
 If *this = #Null Or channel >= #IF_UsedChannels
  ProcedureReturn -1
 EndIf
 *object = *this
 *src = *object\srcMem
 sum = 0
 If channel = -1
  For i = 0 To *object\pixels - 1
   int = Gray(*src\rgba)
   sum + int
   *src + SizeOf(ImageFilter_RGBA)
  Next i
 Else
  For i = 0 To *object\pixels - 1
   int = *src\channel[channel] & $FF
   sum + int
   *src + SizeOf(ImageFilter_RGBA)
  Next i
 EndIf
 ProcedureReturn sum / *object\pixels
EndProcedure


Procedure.f ImageFilter_getStandardDeviation(*this.IImageFilter, channel.i = -1)
 Protected *object.OImageFilter, *src.ImageFilter_RGBA, int.i, sum.q, sqsum.q, m.d
 If *this = #Null Or channel >= #IF_UsedChannels
  ProcedureReturn -1
 EndIf
 *object = *this
 *src = *object\srcMem
 sum = 0
 sqsum = 0
 If channel = -1
  For i = 0 To *object\pixels - 1
   int = Gray(*src\rgba)
   sum + int
   sqsum + Square(int)
   *src + SizeOf(ImageFilter_RGBA)
  Next i
 Else
  For i = 0 To *object\pixels - 1
   int = *src\channel[channel] & $FF
   sum + int
   sqsum + Square(int)
   *src + SizeOf(ImageFilter_RGBA)
  Next i
 EndIf
 m = sum / *object\pixels
 ProcedureReturn Sqr((sqsum / *object\pixels) - Square(m))
EndProcedure


Procedure.f ImageFilter_getCenterOfMassX(*this.IImageFilter, channel.i = -1)
 Protected *object.OImageFilter, *src.ImageFilter_RGBA, int.i, m.q, sum.q
 If *this = #Null Or channel >= #IF_UsedChannels
  ProcedureReturn -1
 EndIf
 *object = *this
 *src = *object\srcMem
 m = 0
 sum = 0
 If channel = -1
  For y = *object\height - 1 To 0 Step -1
   For x = 0 To *object\width - 1
    int = Gray(*src\rgba)
    m + (int * x)
    sum + int
    *src + SizeOf(ImageFilter_RGBA)
   Next x
  Next y
 Else
  For y = *object\height - 1 To 0 Step -1
   For x = 0 To *object\width - 1
    int = *src\channel[channel] & $FF
    m + (int * x)
    *src + SizeOf(ImageFilter_RGBA)
   Next x
  Next y
 EndIf
 ProcedureReturn m / sum
EndProcedure


Procedure.f ImageFilter_getCenterOfMassY(*this.IImageFilter, channel.i = -1)
 Protected *object.OImageFilter, *src.ImageFilter_RGBA, int.i, mx.q, my.q, sum.q
 If *this = #Null Or channel >= #IF_UsedChannels
  ProcedureReturn -1
 EndIf
 *object = *this
 *src = *object\srcMem
 m = 0
 sum = 0
 If channel = -1
  For y = *object\height - 1 To 0 Step -1
   For x = 0 To *object\width - 1
    int = Gray(*src\rgba)
    m + (int * y)
    sum + int
    *src + SizeOf(ImageFilter_RGBA)
   Next x
  Next y
 Else
  For y = *object\height - 1 To 0 Step -1
   For x = 0 To *object\width - 1
    int = *src\channel[channel] & $FF
    m + (int * y)
    sum + int
    *src + SizeOf(ImageFilter_RGBA)
   Next x
  Next y
 EndIf
 ProcedureReturn m / sum
EndProcedure


Procedure.f ImageFilter_getSemimajorAxisAngle(*this.IImageFilter, channel.i = -1)
 Protected *object.OImageFilter, *src.ImageFilter_RGBA, int.i
 Protected mx.q, my.q, mxx.q, mxy.q, myy.q, sum.q
 Protected _mx.d, _my.d, _mxx.d, _mxy.d, _myy.d
 Protected phi.d
 If *this = #Null Or channel >= #IF_UsedChannels
  ProcedureReturn 0
 EndIf
 *object = *this
 *src = *object\srcMem
 mx = 0
 my = 0
 mxx = 0
 mxy = 0
 myy = 0
 sum = 0
 If channel = -1
  For y = *object\height - 1 To 0 Step -1
   For x = 0 To *object\width - 1
    int = Gray(*src\rgba)
    mx + (int * x)
    my + (int * y)
    mxx + (int * x * x)
    mxy + (int * x * y)
    myy + (int * y * y)
    sum + int
    *src + SizeOf(ImageFilter_RGBA)
   Next x
  Next y
 Else
  For y = *object\height - 1 To 0 Step -1
   For x = 0 To *object\width - 1
    int = *src\channel[channel] & $FF
    mx + (int * x)
    my + (int * y)
    mxx + (int * x * x)
    mxy + (int * x * y)
    myy + (int * y * y)
    sum + int
    *src + SizeOf(ImageFilter_RGBA)
   Next x
  Next y
 EndIf
 _mx = mx / sum
 _my = my / sum
 _mxx = (mxx / sum) - (_mx * _mx)
 _mxy = (mxy / sum) - (_mx * _my)
 _myy = (myy / sum) - (_my * _my)
 If _mxx = 0 And _myy = 0
  ProcedureReturn 0
 EndIf
 If _mxy = 0
  If _mxx > _myy
   phi = 0
  Else
   phi = #PI / 2
  EndIf
 Else
  phi = -ATan((2 * _mxy) / ((_mxx - _myy) + Sqr(Square(_mxx - _myy) + (4 * _mxy * _mxy))))
 EndIf
 phi = (phi * 180) / #PI
 ProcedureReturn phi
EndProcedure


Procedure.f ImageFilter_getExcentricity(*this.IImageFilter, channel.i = -1)
 Protected *object.OImageFilter, *src.ImageFilter_RGBA, int.i
 Protected mx.q, my.q, mxx.q, mxy.q, myy.q, sum.q
 Protected _mx.d, _my.d, _mxx.d, _mxy.d, _myy.d
 If *this = #Null Or channel >= #IF_UsedChannels
  ProcedureReturn 0
 EndIf
 *object = *this
 *src = *object\srcMem
 mx = 0
 my = 0
 mxx = 0
 mxy = 0
 myy = 0
 sum = 0
 If channel = -1
  For y = *object\height - 1 To 0 Step -1
   For x = 0 To *object\width - 1
    int = Gray(*src\rgba)
    mx + (int * x)
    my + (int * y)
    mxx + (int * x * x)
    mxy + (int * x * y)
    myy + (int * y * y)
    sum + int
    *src + SizeOf(ImageFilter_RGBA)
   Next x
  Next y
 Else
  For y = *object\height - 1 To 0 Step -1
   For x = 0 To *object\width - 1
    int = *src\channel[channel] & $FF
    mx + (int * x)
    my + (int * y)
    mxx + (int * x * x)
    mxy + (int * x * y)
    myy + (int * y * y)
    sum + int
    *src + SizeOf(ImageFilter_RGBA)
   Next x
  Next y
 EndIf
 _mx = mx / sum
 _my = my / sum
 _mxx = (mxx / sum) - (_mx * _mx)
 _mxy = (mxy / sum) - (_mx * _my)
 _myy = (myy / sum) - (_my * _my)
 If _mxx = 0 And _myy = 0
  ProcedureReturn 0
 EndIf
 ProcedureReturn (Square(_mxx - _myy) + (4 * _mxy * _mxy)) / Square(_mxx + _myy)
EndProcedure


Procedure.i ImageFilter_grayscale(*this.IImageFilter)
 Protected *object.OImageFilter, gray.i, *src.ImageFilter_RGBA
 If *this = #Null
  ProcedureReturn #False
 EndIf
 *object = *this
 *src = *object\srcMem
 For i = 0 To *object\pixels - 1
  gray = Gray(*src\rgba)
  *src\channel[0] = gray
  *src\channel[1] = gray
  *src\channel[2] = gray
  *src + SizeOf(ImageFilter_RGBA)
 Next i
 ProcedureReturn #True
EndProcedure


Procedure.i ImageFilter_invert(*this.IImageFilter)
 Protected *object.OImageFilter, gray.i, *src.ImageFilter_RGBA
 If *this = #Null
  ProcedureReturn #False
 EndIf
 *object = *this
 *src = *object\srcMem
 For i = 0 To *object\pixels - 1
  *src\rgba ! $FFFFFF
  *src + SizeOf(ImageFilter_RGBA)
 Next i
 ProcedureReturn #True
EndProcedure


Procedure.i ImageFilter_brightness(*this.IImageFilter, delta.i)
 Protected *object.OImageFilter
 If *this = #Null
  ProcedureReturn #False
 EndIf
 ProcedureReturn *this\colorScale(1, delta)
EndProcedure


Procedure.i ImageFilter_contrast(*this.IImageFilter, factor.f)
 Protected *object.OImageFilter
 If *this = #Null
  ProcedureReturn #False
 EndIf
 ProcedureReturn *this\colorScale(factor, 0)
EndProcedure


Procedure.i ImageFilter_colorScale(*this.IImageFilter, factor.f = 1, delta.i = 0)
 Protected *object.OImageFilter, int.i, *src.ImageFilter_RGBA
 If *this = #Null
  ProcedureReturn #False
 EndIf
 *object = *this
 *src = *object\srcMem
 For i = 0 To *object\pixels - 1
  For channel = 0 To #IF_UsedChannels - 1
   int = *src\channel[channel] & $FF
   int = Int(factor * (int + delta))
   limit(int, 0, $FF)
   *src\channel[channel] = int
  Next channel
  *src + SizeOf(ImageFilter_RGBA)
 Next i
 ProcedureReturn #True
EndProcedure


Procedure.i ImageFilter_gamma(*this.IImageFilter, g.f)
 Protected *object.OImageFilter, int.i, *src.ImageFilter_RGBA
 If *this = #Null
  ProcedureReturn #False
 EndIf
 If g = 1
  ProcedureReturn #True
 EndIf
 *object = *this
 *src = *object\srcMem
 For i = 0 To *object\pixels - 1
  For channel = 0 To #IF_UsedChannels - 1
   int = *src\channel[channel] & $FF
   int = Pow(int, g)
   limit(int, 0, $FF)
   *src\channel[channel] = int
  Next channel
  *src + SizeOf(ImageFilter_RGBA)
 Next i
 ProcedureReturn #True
EndProcedure


Procedure.i ImageFilter_normalize(*this.IImageFilter)
 Protected *object.OImageFilter, int.i, *src.ImageFilter_RGBA
 Protected Dim g.i(#IF_UsedChannels - 1,1), Dim c.f(#IF_UsedChannels - 1,1)
 If *this = #Null
  ProcedureReturn #False
 EndIf
 *object = *this
 For channel = 0 To #IF_UsedChannels - 1
  g(channel, 0) = $FF
  g(channel, 1) = 0
 Next channel
 *src = *object\srcMem
 For i = 0 To *object\pixels - 1
  For channel = 0 To #IF_UsedChannels - 1
   int = *src\channel[channel] & $FF
   If g(channel, 0) > int : g(channel, 0) = int : EndIf
   If g(channel, 1) < int : g(channel, 1) = int : EndIf
  Next channel
  *src + SizeOf(ImageFilter_RGBA)
 Next i
 For channel = 0 To #IF_UsedChannels - 1
  c(channel, 0) = -g(channel, 0)
  c(channel, 1) = $FF / (g(channel, 1) - g(channel, 0))
 Next channel
 *src = *object\srcMem
 For i = 0 To *object\pixels - 1
  For channel = 0 To #IF_UsedChannels - 1
   int = *src\channel[channel] & $FF
   int = Int(c(channel, 1) * (c(channel, 0) + int))
   limit(int, 0, $FF)
   *src\channel[channel] = int
  Next channel
  *src + SizeOf(ImageFilter_RGBA)
 Next i
 ProcedureReturn #True
EndProcedure


Procedure.i ImageFilter_mirrorVertical(*this.IImageFilter)
 Protected *object.OImageFilter, *dest.ImageFilter_RGBA, *destMem.ImageFilter_RGBA
 If *this = #Null
  ProcedureReturn #False
 EndIf
 *object = *this
 *destMem = AllocateMemory(*object\pixels * SizeOf(ImageFilter_RGBA))
 If *destMem = #Null
  ProcedureReturn #False
 EndIf
 *dest = *destMem
 For y = 0 To *object\height - 1
  For x = 0 To *object\width - 1
   *dest\rgba = getColorFromArray(*object\srcMem, x, *object\height - 1 - y, *object\width)
   *dest + SizeOf(ImageFilter_RGBA)
  Next x
 Next y
 FreeMemory(*object\srcMem)
 *object\srcMem = *destMem
 ProcedureReturn #True
EndProcedure


Procedure.i ImageFilter_mirrorHorizontal(*this.IImageFilter)
 Protected *object.OImageFilter, *dest.ImageFilter_RGBA, *destMem.ImageFilter_RGBA
 If *this = #Null
  ProcedureReturn #False
 EndIf
 *object = *this
 *destMem = AllocateMemory(*object\pixels * SizeOf(ImageFilter_RGBA))
 If *destMem = #Null
  ProcedureReturn #False
 EndIf
 *dest = *destMem
 For y = 0 To *object\height - 1
  For x = 0 To *object\width - 1
   *dest\rgba = getColorFromArray(*object\srcMem, *object\width - 1 - x, y, *object\width)
   *dest + SizeOf(ImageFilter_RGBA)
  Next x
 Next y
 FreeMemory(*object\srcMem)
 *object\srcMem = *destMem
 ProcedureReturn #True
EndProcedure


Procedure.i ImageFilter_rotate(*this.IImageFilter, angle.f, nonBilinear.i = #False, resize.i = #False)
 Protected *object.OImageFilter, *dest.ImageFilter_RGBA, *destMem.ImageFilter_RGBA
 Protected halfWidth.f, halfHeight.f, cosAngle.f, sinAngle.f, oX.f, oY.f, oXr.i, oYr.i, difX.f, difY.f
 Protected s00.ImageFilter_RGBA, s01.ImageFilter_RGBA, s10.ImageFilter_RGBA, s11.ImageFilter_RGBA
 Protected int00.i, int01.i, int10.i, int11.i, int.i
 Protected newImage.i, newWidth.i, newHeight.i, newPixels.i
 Protected newHalfWidth.f, newHalfHeight.f
 If *this = #Null
  ProcedureReturn #False
 EndIf
 *object = *this
 cosAngle = Cos(((-angle) / 180) * #PI)
 sinAngle = Sin(((-angle) / 180) * #PI)
 halfWidth = *object\width / 2
 halfHeight = *object\height / 2
 If resize
  Protected x1.f, x2.f, x3.f, x4.f, minX.f, maxX.f
  Protected y1.f, y2.f, y3.f, y4.f, minY.f, maxY.f
  x1 = ((-sinAngle) * (0 - halfHeight)) + (cosAngle * (0 - halfWidth)) + halfWidth
  y1 = (cosAngle * (0 - halfHeight)) + (sinAngle * (0 - halfWidth)) + halfHeight
  x2 = ((-sinAngle) * (0 - halfHeight)) + (cosAngle * (*object\width - 1 - halfWidth)) + halfWidth
  y2 = (cosAngle * (0 - halfHeight)) + (sinAngle * (*object\width - 1 - halfWidth)) + halfHeight
  x3 = ((-sinAngle) * (*object\height - 1 - halfHeight)) + (cosAngle * (0 - halfWidth)) + halfWidth
  y3 = (cosAngle * (*object\height - 1 - halfHeight)) + (sinAngle * (0 - halfWidth)) + halfHeight
  x4 = ((-sinAngle) * (*object\height - 1 - halfHeight)) + (cosAngle * (*object\width - 1 - halfWidth)) + halfWidth
  y4 = (cosAngle * (*object\height - 1 - halfHeight)) + (sinAngle * (*object\width - 1 - halfWidth)) + halfHeight
  minX = x1
  minY = y1
  If minX > x2 : minX = x2 : EndIf
  If minY > y2 : minY = y2 : EndIf
  If minX > x3 : minX = x3 : EndIf
  If minY > y3 : minY = y3 : EndIf
  If minX > x4 : minX = x4 : EndIf
  If minY > y4 : minY = y4 : EndIf
  maxX = x1
  maxY = y1
  If maxX < x2 : maxX = x2 : EndIf
  If maxY < y2 : maxY = y2 : EndIf
  If maxX < x3 : maxX = x3 : EndIf
  If maxY < y3 : maxY = y3 : EndIf
  If maxX < x4 : maxX = x4 : EndIf
  If maxY < y4 : maxY = y4 : EndIf
  newWidth = maxX - minX + 1
  newHeight = maxY - minY + 1
  newPixels = newWidth * newHeight
  newHalfWidth = (maxX - minX + 1) / 2
  newHalfHeight = (maxY - minY + 1) / 2
  newImage = CreateImage(#PB_Any, newWidth, newHeight, #IF_ImageDepth)
  If newImage = #Null
   ProcedureReturn #False
  EndIf
 Else
  newWidth = *object\width
  newHeight = *object\height
  newPixels = *object\pixels
  newHalfWidth = halfWidth
  newHalfHeight = halfHeight
 EndIf
 *destMem = AllocateMemory(newPixels * SizeOf(ImageFilter_RGBA))
 If *destMem = #Null
  If IsImage(newImage)
   FreeImage(newImage)
  EndIf
  ProcedureReturn #False
 EndIf
 *dest = *destMem
 If nonBilinear
  For y = 0 To newHeight - 1
   For x = 0 To newWidth - 1
    oXr = Round(((-sinAngle) * (y - newHalfHeight)) + (cosAngle * (x - newHalfWidth)) + halfWidth, #PB_Round_Nearest)
    oYr = Round((cosAngle * (y - newHalfHeight)) + (sinAngle * (x - newHalfWidth)) + halfHeight, #PB_Round_Nearest)
    If 0 <= oYr And oYr < *object\height And 0 <= oXr And oXr < *object\width
     s00\rgba = getColorFromArray(*object\srcMem, oXr, oYr, *object\width)
    Else : s00\rgba = 0 : EndIf
    For channel = 0 To #IF_UsedChannels - 1
     int = s00\channel[channel] & $FF
     limit(int, 0, $FF)
     *dest\channel[channel] = int
    Next channel
    *dest + SizeOf(ImageFilter_RGBA)
   Next x
  Next y
 Else
  For y = 0 To newHeight - 1
   For x = 0 To newWidth - 1
    oX = ((-sinAngle) * (y - newHalfHeight)) + (cosAngle * (x - newHalfWidth)) + halfWidth
    oY = (cosAngle * (y - newHalfHeight)) + (sinAngle * (x - newHalfWidth)) + halfHeight
    oXr = Round(oX, #PB_Round_Down)
    oYr = Round(oY, #PB_Round_Down)
    If 0 <= oYr And oYr < *object\height And 0 <= oXr And oXr < *object\width
     s00\rgba = getColorFromArray(*object\srcMem, oXr, oYr, *object\width)
    Else : s00\rgba = 0 : EndIf
    If 0 <= oYr And oYr < *object\height And 0 <= oXr + 1 And oXr + 1 < *object\width
     s01\rgba = getColorFromArray(*object\srcMem, oXr + 1, oYr, *object\width)
    Else : s01\rgba = 0 : EndIf
    If 0 <= oYr + 1 And oYr + 1 < *object\height And 0 <= oXr And oXr < *object\width
     s10\rgba = getColorFromArray(*object\srcMem, oXr, oYr + 1, *object\width)
    Else : s10\rgba = 0 : EndIf
    If 0 <= oYr + 1 And oYr + 1 < *object\height And 0 <= oXr + 1 And oXr + 1 < *object\width
     s11\rgba = getColorFromArray(*object\srcMem, oXr + 1, oYr + 1, *object\width)
    Else : s11\rgba = 0 : EndIf
    difX = oX - oXr
    difY = oY - oYr
    For channel = 0 To #IF_UsedChannels - 1
     int00 = s00\channel[channel] & $FF
     int01 = s01\channel[channel] & $FF
     int10 = s10\channel[channel] & $FF
     int11 = s11\channel[channel] & $FF
     int = Int(((1 - difY) * ((int00 * (1 - difX)) + (int01 * difX))) + (difY * ((int10 * (1 - difX)) + (int11 * difX))))
     limit(int, 0, $FF)
     *dest\channel[channel] = int
    Next channel
    *dest + SizeOf(ImageFilter_RGBA)
   Next x
  Next y
 EndIf
 FreeMemory(*object\srcMem)
 *object\srcMem = *destMem
 If resize
  If IsImage(*object\image)
   FreeImage(*object\image)
  EndIf
  *object\image = newImage
  *object\width = newWidth
  *object\height = newHeight
  *object\pixels = newPixels
 EndIf
 ProcedureReturn #True
EndProcedure


Procedure.i ImageFilter_resize(*this.IImageFilter, newWidth.i, newHeight.i, mode.i)
 Protected *object.OImageFilter, *dest.ImageFilter_RGBA, *destMem.ImageFilter_RGBA
 Protected color.ImageFilter_RGBA
 Protected newImage.i, newPixels.i
 Protected scaleX.f, scaleY.f, wX.f, wY.f
 Protected sX.i, eX.i, sY.i, eY.i, refPixels.i
 Protected Dim newColor.i(#IF_UsedChannels - 1), int.i
 If *this = #Null Or newWidth < 1 Or newHeight < 1
  ProcedureReturn #False
 EndIf
 *object = *this
 If *object\width = newWidth And *object\height = newHeight
  ProcedureReturn #True
 EndIf
 scaleX = *object\width / newWidth
 scaleY = *object\height / newHeight
 wX = scaleX / 2
 wY = scaleY / 2
 newPixels = newWidth * newHeight
 newImage = CreateImage(#PB_Any, newWidth, newHeight, #IF_ImageDepth)
 If newImage = #Null
  ProcedureReturn #False
 EndIf
 *destMem = AllocateMemory(newPixels * SizeOf(ImageFilter_RGBA))
 If *destMem = #Null
  If IsImage(newImage)
   FreeImage(newImage)
  EndIf
  ProcedureReturn #False
 EndIf
 *dest = *destMem
 Select mode
  Case #IF_RM_NearestNeighbor
   For y = 0 To newHeight - 1
    For x = 0 To newWidth - 1
     For channel = 0 To #IF_UsedChannels - 1
      newColor(channel) = 0
     Next channel
     refPixels = 0
     sX = Round((x * scaleX) - wX, #PB_Round_Nearest)
     eX = Round((x * scaleX) + wX, #PB_Round_Nearest)
     limit(sX, 0, *object\width - 1)
     limit(eX, 0, *object\width - 1)
     sY = Round((y * scaleY) - wY, #PB_Round_Nearest)
     eY = Round((y * scaleY) + wY, #PB_Round_Nearest)
     limit(sY, 0, *object\height - 1)
     limit(eY, 0, *object\height - 1)
     For yn = sY To eY
      For xn = sX To eX
       color\rgba = getColorFromArray(*object\srcMem, xn, yn, *object\width)
       For channel = 0 To #IF_UsedChannels - 1
        int = color\channel[channel] & $FF
        newColor(channel) + int
       Next channel
       refPixels + 1
      Next xn
     Next yn
     For channel = 0 To #IF_UsedChannels - 1
      int = Round(newColor(channel) / refPixels, #PB_Round_Nearest)
      limit(int, 0, $FF)
      *dest\channel[channel] = int
     Next channel
     *dest + SizeOf(ImageFilter_RGBA)
    Next x
   Next y
  Default
   If IsImage(newImage)
    FreeImage(newImage)
   EndIf
   If *destMem
    FreeMemory(*destMem)
   EndIf
   ProcedureReturn #False
 EndSelect
 FreeMemory(*object\srcMem)
 *object\srcMem = *destMem
 If IsImage(*object\image)
  FreeImage(*object\image)
 EndIf
 *object\image = newImage
 *object\width = newWidth
 *object\height = newHeight
 *object\pixels = newPixels
 ProcedureReturn #True
EndProcedure


Procedure.i ImageFilter_add(*this.IImageFilter, *image.IImageFilter, factor.f = 1, delta.i = 0)
 Protected *object.OImageFilter
 Protected *src.ImageFilter_RGBA, *dest.ImageFilter_RGBA
 Protected s.i, d.i
 Protected int.i
 If *this = #Null Or *image = #Null
  ProcedureReturn #False
 EndIf
 *object = *this
 If *object\width <> *image\getWidth() Or *object\height <> *image\getHeight()
  ProcedureReturn #False
 EndIf
 *src = *image\getImageMem()
 *dest = *object\srcMem
 For i = 0 To *object\pixels - 1
  For channel = 0 To #IF_UsedChannels - 1
   s = (*src\channel[channel] & $FF)
   d = (*dest\channel[channel] & $FF)
   int = Int(((d + s) * factor) + delta)
   limit(int, 0, $FF)
   *dest\channel[channel] = int
  Next
  *src + SizeOf(ImageFilter_RGBA)
  *dest + SizeOf(ImageFilter_RGBA)
 Next
 ProcedureReturn #True
EndProcedure


Procedure.i ImageFilter_sub(*this.IImageFilter, *image.IImageFilter, factor.f = 1, delta.i = 0)
 Protected *object.OImageFilter
 Protected *src.ImageFilter_RGBA, *dest.ImageFilter_RGBA
 Protected s.i, d.i
 Protected int.i
 If *this = #Null Or *image = #Null
  ProcedureReturn #False
 EndIf
 *object = *this
 If *object\width <> *image\getWidth() Or *object\height <> *image\getHeight()
  ProcedureReturn #False
 EndIf
 *src = *image\getImageMem()
 *dest = *object\srcMem
 For i = 0 To *object\pixels - 1
  For channel = 0 To #IF_UsedChannels - 1
   s = (*src\channel[channel] & $FF)
   d = (*dest\channel[channel] & $FF)
   int = Int(((d - s) * factor) + delta)
   limit(int, 0, $FF)
   *dest\channel[channel] = int
  Next
  *src + SizeOf(ImageFilter_RGBA)
  *dest + SizeOf(ImageFilter_RGBA)
 Next
 ProcedureReturn #True
EndProcedure


Procedure.i ImageFilter_mul(*this.IImageFilter, *image.IImageFilter, factor.f = 1, delta.i = 0)
 Protected *object.OImageFilter
 Protected *src.ImageFilter_RGBA, *dest.ImageFilter_RGBA
 Protected s.i, d.i
 Protected int.i
 If *this = #Null Or *image = #Null
  ProcedureReturn #False
 EndIf
 *object = *this
 If *object\width <> *image\getWidth() Or *object\height <> *image\getHeight()
  ProcedureReturn #False
 EndIf
 *src = *image\getImageMem()
 *dest = *object\srcMem
 For i = 0 To *object\pixels - 1
  For channel = 0 To #IF_UsedChannels - 1
   s = (*src\channel[channel] & $FF)
   d = (*dest\channel[channel] & $FF)
   int = Int((d * s * factor) + delta)
   limit(int, 0, $FF)
   *dest\channel[channel] = int
  Next
  *src + SizeOf(ImageFilter_RGBA)
  *dest + SizeOf(ImageFilter_RGBA)
 Next
 ProcedureReturn #True
EndProcedure


Procedure.i ImageFilter_div(*this.IImageFilter, *image.IImageFilter, factor.f = 1, delta.i = 0)
 Protected *object.OImageFilter
 Protected *src.ImageFilter_RGBA, *dest.ImageFilter_RGBA
 Protected s.i, d.i
 Protected int.i
 If *this = #Null Or *image = #Null
  ProcedureReturn #False
 EndIf
 *object = *this
 If *object\width <> *image\getWidth() Or *object\height <> *image\getHeight()
  ProcedureReturn #False
 EndIf
 *src = *image\getImageMem()
 *dest = *object\srcMem
 For i = 0 To *object\pixels - 1
  For channel = 0 To #IF_UsedChannels - 1
   s = (*src\channel[channel] & $FF)
   d = (*dest\channel[channel] & $FF)
   If s > 0
    int = Int((d * factor / s) + delta)
   Else
    int = $FF
   EndIf
   limit(int, 0, $FF)
   *dest\channel[channel] = int
  Next
  *src + SizeOf(ImageFilter_RGBA)
  *dest + SizeOf(ImageFilter_RGBA)
 Next
 ProcedureReturn #True
EndProcedure


Procedure.i ImageFilter_xor(*this.IImageFilter, *image.IImageFilter)
 Protected *object.OImageFilter
 Protected *src.ImageFilter_RGBA, *dest.ImageFilter_RGBA
 If *this = #Null Or *image = #Null
  ProcedureReturn #False
 EndIf
 *object = *this
 If *object\width <> *image\getWidth() Or *object\height <> *image\getHeight()
  ProcedureReturn #False
 EndIf
 *src = *image\getImageMem()
 *dest = *object\srcMem
 For i = 0 To *object\pixels - 1
  *dest\rgba ! *src\rgba
  *src + SizeOf(ImageFilter_RGBA)
  *dest + SizeOf(ImageFilter_RGBA)
 Next
 ProcedureReturn #True
EndProcedure


Procedure.i ImageFilter_and(*this.IImageFilter, *image.IImageFilter)
 Protected *object.OImageFilter
 Protected *src.ImageFilter_RGBA, *dest.ImageFilter_RGBA
 If *this = #Null Or *image = #Null
  ProcedureReturn #False
 EndIf
 *object = *this
 If *object\width <> *image\getWidth() Or *object\height <> *image\getHeight()
  ProcedureReturn #False
 EndIf
 *src = *image\getImageMem()
 *dest = *object\srcMem
 For i = 0 To *object\pixels - 1
  *dest\rgba & *src\rgba
  *src + SizeOf(ImageFilter_RGBA)
  *dest + SizeOf(ImageFilter_RGBA)
 Next
 ProcedureReturn #True
EndProcedure


Procedure.i ImageFilter_or(*this.IImageFilter, *image.IImageFilter)
 Protected *object.OImageFilter
 Protected *src.ImageFilter_RGBA, *dest.ImageFilter_RGBA
 If *this = #Null Or *image = #Null
  ProcedureReturn #False
 EndIf
 *object = *this
 If *object\width <> *image\getWidth() Or *object\height <> *image\getHeight()
  ProcedureReturn #False
 EndIf
 *src = *image\getImageMem()
 *dest = *object\srcMem
 For i = 0 To *object\pixels - 1
  *dest\rgba | *src\rgba
  *src + SizeOf(ImageFilter_RGBA)
  *dest + SizeOf(ImageFilter_RGBA)
 Next
 ProcedureReturn #True
EndProcedure


Top
 Profile  
 
 Post subject: Re: class for image manipulation (OOP)
PostPosted: Fri Apr 13, 2012 6:33 pm 
Offline
User
User
User avatar

Joined: Sat May 22, 2004 1:38 am
Posts: 69
Part 2/2
Code:

Procedure.i ImageFilter_weight(*this.IImageFilter, *image.IImageFilter, factor.f = 1, delta.i = 0)
 Protected *object.OImageFilter
 Protected *src.ImageFilter_RGBA, *dest.ImageFilter_RGBA
 Protected s.i, d.i
 Protected int.i
 If *this = #Null Or *image = #Null
  ProcedureReturn #False
 EndIf
 *object = *this
 If *object\width <> *image\getWidth() Or *object\height <> *image\getHeight()
  ProcedureReturn #False
 EndIf
 *src = *image\getImageMem()
 *dest = *object\srcMem
 For i = 0 To *object\pixels - 1
  For channel = 0 To #IF_UsedChannels - 1
   s = (*src\channel[channel] & $FF)
   d = (*dest\channel[channel] & $FF)
   If s > 0
    int = Int((factor * d * 255 / s) + delta)
   Else
    int = 0
   EndIf
   limit(int, 0, $FF)
   *dest\channel[channel] = int
  Next
  *src + SizeOf(ImageFilter_RGBA)
  *dest + SizeOf(ImageFilter_RGBA)
 Next
 ProcedureReturn #True
EndProcedure


Procedure.i ImageFilter_weightMask(*this.IImageFilter, *image.IImageFilter, *mask.IImageFilter, factor.f = 1, delta.i = 0)
 Protected *object.OImageFilter
 Protected *src.ImageFilter_RGBA, *msk.ImageFilter_RGBA, *dest.ImageFilter_RGBA
 Protected s.i, m.i, d.i
 Protected int.i
 If *this = #Null Or *image = #Null Or *mask = #Null
  ProcedureReturn #False
 EndIf
 *object = *this
 If *object\width <> *image\getWidth() Or *object\height <> *image\getHeight() Or *object\width <> *mask\getWidth() Or *object\height <> *mask\getHeight()
  ProcedureReturn #False
 EndIf
 *src = *image\getImageMem()
 *msk = *mask\getImageMem()
 *dest = *object\srcMem
 For i = 0 To *object\pixels - 1
  For channel = 0 To #IF_UsedChannels - 1
   s = (*src\channel[channel] & $FF)
   m = (*msk\channel[channel] & $FF)
   d = (*dest\channel[channel] & $FF)
   int = Int((((d * ($FF - m)) + (s * m)) * factor / $FF) + delta)
   limit(int, 0, $FF)
   *dest\channel[channel] = int
  Next
  *src + SizeOf(ImageFilter_RGBA)
  *msk + SizeOf(ImageFilter_RGBA)
  *dest + SizeOf(ImageFilter_RGBA)
 Next
 ProcedureReturn #True
EndProcedure


Procedure.i ImageFilter_difference(*this.IImageFilter, *image.IImageFilter, factor.f = 1, delta.i = 0)
 Protected *object.OImageFilter
 Protected *src.ImageFilter_RGBA, *dest.ImageFilter_RGBA
 Protected s.i, d.i
 Protected int.i
 If *this = #Null Or *image = #Null
  ProcedureReturn #False
 EndIf
 *object = *this
 If *object\width <> *image\getWidth() Or *object\height <> *image\getHeight()
  ProcedureReturn #False
 EndIf
 *src = *image\getImageMem()
 *dest = *object\srcMem
 For i = 0 To *object\pixels - 1
  For channel = 0 To #IF_UsedChannels - 1
   s = (*src\channel[channel] & $FF)
   d = (*dest\channel[channel] & $FF)
   int = Int((factor * Abs(d - s)) + delta)
   limit(int, 0, $FF)
   *dest\channel[channel] = int
  Next
  *src + SizeOf(ImageFilter_RGBA)
  *dest + SizeOf(ImageFilter_RGBA)
 Next
 ProcedureReturn #True
EndProcedure


Procedure.i ImageFilter_euclidianNorm(*this.IImageFilter, *image.IImageFilter, offset.i)
 Protected *object.OImageFilter
 Protected *src.ImageFilter_RGBA, *dest.ImageFilter_RGBA
 Protected s.i, d.i
 Protected int.i
 If *this = #Null Or *image = #Null
  ProcedureReturn #False
 EndIf
 *object = *this
 If *object\width <> *image\getWidth() Or *object\height <> *image\getHeight()
  ProcedureReturn #False
 EndIf
 *src = *image\getImageMem()
 *dest = *object\srcMem
 For i = 0 To *object\pixels - 1
  For channel = 0 To #IF_UsedChannels - 1
   s = (*src\channel[channel] & $FF)
   d = (*dest\channel[channel] & $FF)
   int = Int(Sqr(Square(d - offset) + Square(s - offset)) + offset)
   limit(int, 0, $FF)
   *dest\channel[channel] = int
  Next
  *src + SizeOf(ImageFilter_RGBA)
  *dest + SizeOf(ImageFilter_RGBA)
 Next
 ProcedureReturn #True
EndProcedure


Procedure.i ImageFilter_manhattenNorm(*this.IImageFilter, *image.IImageFilter, offset.i)
 Protected *object.OImageFilter
 Protected *src.ImageFilter_RGBA, *dest.ImageFilter_RGBA
 Protected s.i, d.i
 Protected int.i
 If *this = #Null Or *image = #Null
  ProcedureReturn #False
 EndIf
 *object = *this
 If *object\width <> *image\getWidth() Or *object\height <> *image\getHeight()
  ProcedureReturn #False
 EndIf
 *src = *image\getImageMem()
 *dest = *object\srcMem
 For i = 0 To *object\pixels - 1
  For channel = 0 To #IF_UsedChannels - 1
   s = (*src\channel[channel] & $FF)
   d = (*dest\channel[channel] & $FF)
   int = Int(Abs(d - offset) + Abs(s - offset) + offset)
   limit(int, 0, $FF)
   *dest\channel[channel] = int
  Next
  *src + SizeOf(ImageFilter_RGBA)
  *dest + SizeOf(ImageFilter_RGBA)
 Next
 ProcedureReturn #True
EndProcedure


Procedure.i ImageFilter_addColorOverlay(*this.IImageFilter, color.i, opacity.f)
 Protected *object.OImageFilter, dest.ImageFilter_RGBA
 Protected *src.ImageFilter_RGBA
 Protected int1.i, int2.i
 If *this = #Null
  ProcedureReturn #False
 EndIf
 *object = *this
 If opacity < 0 Or opacity > 1
  ProcedureReturn #False
 EndIf
 dest\rgba = color
 *src = *object\srcMem
 For i = 0 To *object\pixels - 1
  For channel = 0 To #IF_UsedChannels - 1
   int1 = *src\channel[channel] & $FF
   int2 = dest\channel[channel] & $FF
   int1 = Int((int1 * (1 - opacity)) + (int2 * opacity))
   limit(int1, 0, $FF)
   *src\channel[channel] = int1
  Next channel
  *src + SizeOf(ImageFilter_RGBA)
 Next i
 ProcedureReturn #True
EndProcedure


Procedure.i ImageFilter_removeColorOverlay(*this.IImageFilter, color.i, opacity.f)
 Protected *object.OImageFilter, dest.ImageFilter_RGBA
 Protected *src.ImageFilter_RGBA
 Protected int1.i, int2.i
 If *this = #Null
  ProcedureReturn #False
 EndIf
 *object = *this
 If opacity <= 0 Or opacity >= 1
  ProcedureReturn #False
 EndIf
 dest\rgba = color
 *src = *object\srcMem
 For i = 0 To *object\pixels - 1
  For channel = 0 To #IF_UsedChannels - 1
   int1 = *src\channel[channel] & $FF
   int2 = dest\channel[channel] & $FF
   int1 = Int(((int2 * opacity) - int1) / (opacity - 1))
   limit(int1, 0, $FF)
   *src\channel[channel] = int1
  Next channel
  *src + SizeOf(ImageFilter_RGBA)
 Next i
 ProcedureReturn #True
EndProcedure


Procedure.i ImageFilter_median(*this.IImageFilter, size.i)
 Protected *object.OImageFilter, src.ImageFilter_RGBA, *dest.ImageFilter_RGBA, *destMem.ImageFilter_RGBA
 Protected Dim radix.i(255), half.i, median.i, index.i
 If *this = #Null Or size < 1
  ProcedureReturn #False
 EndIf
 *object = *this
 half = ((size * 2 + 1) * (size * 2 + 1)) >> 1
 *destMem = AllocateMemory(*object\pixels * SizeOf(ImageFilter_RGBA))
 If *destMem = #Null
  ProcedureReturn #False
 EndIf
 *dest = *destMem
 For y = 0 To *object\height - 1
  For x = 0 To *object\width - 1
   For channel = 0 To #IF_UsedChannels - 1
    For yi = y - size To y + size
     For xi = x - size To x + size
      If xi > 0 And yi > 0 And xi < *object\width And yi < *object\height
       src\rgba = getColorFromArray(*object\srcMem, xi, yi, *object\width)
       radix(src\channel[channel] & $FF) + 1
      EndIf
     Next xi
    Next yi
    median = 0
    index = 255
    For i = 0 To 255
     median + radix(i)
     radix(i) = 0
     If median >= half
      index = i
      For j = i + 1 To 255
       radix(j) = 0
      Next j
      Break 1
     EndIf
    Next i
    *dest\channel[channel] = index
   Next channel
   *dest + SizeOf(ImageFilter_RGBA)
  Next x
 Next y
 FreeMemory(*object\srcMem)
 *object\srcMem = *destMem
 ProcedureReturn #True
EndProcedure


Procedure.i ImageFilter_nearMedian(*this.IImageFilter, normalSize.i, nearSize.i)
 Protected *object.OImageFilter, src.ImageFilter_RGBA, *dest.ImageFilter_RGBA, *destMem.ImageFilter_RGBA
 Protected Dim radix.i(255), half.i, median.i, index.i
 Protected dif.i, minDif.i, minDifColor.ImageFilter_RGBA, int1.i, int2.i
 If *this = #Null Or normalSize < 1 Or nearSize < 1
  ProcedureReturn #False
 EndIf
 *object = *this
 half = ((normalSize * 2 + 1) * (normalSize * 2 + 1)) >> 1
 *destMem = AllocateMemory(*object\pixels * SizeOf(ImageFilter_RGBA))
 If *destMem = #Null
  ProcedureReturn #False
 EndIf
 *dest = *destMem
 For y = 0 To *object\height - 1
  For x = 0 To *object\width - 1
   For channel = 0 To #IF_UsedChannels - 1
    For yi = y - normalSize To y + normalSize
     For xi = x - normalSize To x + normalSize
      If xi > 0 And yi > 0 And xi < *object\width And yi < *object\height
       src\rgba = getColorFromArray(*object\srcMem, xi, yi, *object\width)
       radix(src\channel[channel] & $FF) + 1
      EndIf
     Next xi
    Next yi
    median = 0
    index = 255
    For i = 0 To 255
     median + radix(i)
     radix(i) = 0
     If median >= half
      index = i
      For j = i + 1 To 255
       radix(j) = 0
      Next j
      Break 1
     EndIf
    Next i
    *dest\channel[channel] = index
   Next channel
   minDif = $300
   minDifColor\rgba = *dest\rgba
   For yi = y - nearSize To y + nearSize
    For xi = x - nearSize To x + nearSize
     If xi > 0 And yi > 0 And xi < *object\width And yi < *object\height
      src\rgba = getColorFromArray(*object\srcMem, xi, yi, *object\width)
      dif = 0
      For channel = 0 To #IF_UsedChannels - 1
       int1 = src\channel[channel] & $FF
       int2 = *dest\channel[channel] & $FF
       dif + Abs(int1 - int2)
      Next channel
      If dif < minDif
       minDif = dif
       minDifColor\rgba = src\rgba
      EndIf
     EndIf
    Next xi
   Next yi
   *dest\rgba = minDifColor\rgba
   *dest + SizeOf(ImageFilter_RGBA)
  Next x
 Next y
 FreeMemory(*object\srcMem)
 *object\srcMem = *destMem
 ProcedureReturn #True
EndProcedure


Procedure.i ImageFilter_binomial(*this.IImageFilter, size.i)
 Protected *object.OImageFilter, *destMem.ImageFilter_RGBA
 If *this = #Null Or size < 2
  ProcedureReturn #False
 EndIf
 *object = *this
 *destMem = *this\memBinomial(*object\srcMem, size)
 If *destMem
  FreeMemory(*object\srcMem)
  *object\srcMem = *destMem
 EndIf
 ProcedureReturn #True
EndProcedure


Procedure.i ImageFilter_minMax(*this.IImageFilter, size.i)
 Protected *object.OImageFilter, src.ImageFilter_RGBA, *dest.ImageFilter_RGBA, *destMem.ImageFilter_RGBA
 Protected Dim radix.i(255), min.i, max.i
 If *this = #Null Or size < 1
  ProcedureReturn #False
 EndIf
 *object = *this
 *destMem = AllocateMemory(*object\pixels * SizeOf(ImageFilter_RGBA))
 If *destMem = #Null
  ProcedureReturn #False
 EndIf
 *dest = *destMem
 For y = 0 To *object\height - 1
  For x = 0 To *object\width - 1
   For channel = 0 To #IF_UsedChannels - 1
    For yi = y - size To y + size
     For xi = x - size To x + size
      If xi > 0 And yi > 0 And xi < *object\width And yi < *object\height
       src\rgba = getColorFromArray(*object\srcMem, xi, yi, *object\width)
       radix(src\channel[channel] & $FF) + 1
      EndIf
     Next xi
    Next yi
    min = -1
    max = -1
    For i = 0 To 255
     If radix(i) = 0
      If max = -1
       min = i
      EndIf
     Else
      max = i
     EndIf
     radix(i) = 0
    Next i
    *dest\channel[channel] = max - min - 1
   Next channel
   *dest + SizeOf(ImageFilter_RGBA)
  Next x
 Next y
 FreeMemory(*object\srcMem)
 *object\srcMem = *destMem
 ProcedureReturn #True
EndProcedure


Procedure.i ImageFilter_DoG(*this.IImageFilter, q.i, p.i)
 Protected *object.OImageFilter, *qMem.ImageFilter_RGBA, *pMem.ImageFilter_RGBA
 Protected *src.ImageFilter_RGBA, *q.ImageFilter_RGBA, *p.ImageFilter_RGBA
 Protected int.i
 If *this = #Null Or p < 1 Or p < 1
  ProcedureReturn #False
 EndIf
 *object = *this
 *pMem = *this\memBinomial(*object\srcMem, p)
 If *pMem = #Null
  ProcedureReturn #False
 EndIf
 *qMem = *this\memBinomial(*pMem, q)
 If *qMem = #Null
  FreeMemory(*pMem)
  ProcedureReturn #False
 EndIf
 *src = *object\srcMem
 *p = *pMem
 *q = *qMem
 For y = 0 To *object\height - 1
  For x = 0 To *object\width - 1
   For channel = 0 To #IF_UsedChannels - 1
    int = (4 * ((*q\channel[channel] & $FF) - (*p\channel[channel] & $FF))) + 128
    limit(int, 0, $FF)
    *src\channel[channel] = int
   Next
   *src + SizeOf(ImageFilter_RGBA)
   *p + SizeOf(ImageFilter_RGBA)
   *q + SizeOf(ImageFilter_RGBA)
  Next
 Next
 FreeMemory(*pMem)
 FreeMemory(*qMem)
 ProcedureReturn #True
EndProcedure


Procedure.i ImageFilter_houghTransformation(*this.IImageFilter, threshold.i)
 Protected *object.OImageFilter, *src.ImageFilter_RGBA, int.i
 Protected *dest.ImageFilter_RGBA, *destMem.ImageFilter_RGBA
 Protected halfWidth.i, halfHeight.i, imgId.i
 If *this = #Null
  ProcedureReturn #False
 EndIf
 *object = *this
 halfWidth = *object\width >> 1
 halfHeight = *object\height >> 1
 limit(threshold, 0, $FF)
 Protected width.i, height.i, thetaCos.i, d.i
 width = 360 ;degree
 height = Int(Sqr((halfWidth * halfWidth) + (halfHeight * halfHeight))) ;diagonal
 *destMem = AllocateMemory(width * height * SizeOf(ImageFilter_RGBA))
 If *destMem = #Null
  ProcedureReturn #False
 EndIf
 Protected Dim thetaSin.f(360 + 90 - 1)
 Protected Dim houghField.i(width - 1, height - 1, #IF_UsedChannels - 1)
 Protected Dim maxValue.i(#IF_UsedChannels - 1)
 For theta = 0 To 360 + 90 - 1
  thetaSin(theta) = Sin(theta * 0.017453292519943295)
 Next theta
 *src = *object\srcMem
 For y = 0 To *object\height - 1
  For x = 0 To *object\width - 1
   For theta = 0 To 360 - 1
    d = Int(Abs(((y - halfHeight) * thetaSin(theta)) + ((x - halfWidth) * thetaSin(theta + 90))))
    If d >= 0 And d < height
     For channel = 0 To #IF_UsedChannels - 1
      int = *src\channel[channel] & $FF
      If int >= threshold
       houghField(theta, d, channel) + int
      EndIf
     Next channel
    EndIf
   Next theta
   *src + SizeOf(ImageFilter_RGBA)
  Next x
 Next y
 For channel = 0 To #IF_UsedChannels - 1
  maxValue(channel) = 1
 Next channel
 For y = 0 To height - 1
  For x = 0 To width - 1
   For channel = 0 To #IF_UsedChannels - 1
    If houghField(x, y, channel) > maxValue(channel)
     maxValue(channel) = houghField(x, y, channel)
    EndIf
   Next channel
  Next x
 Next y
 imgId = CreateImage(#PB_Any, width, height, #IF_ImageDepth)
 If IsImage(imgId) = #Null
  ProcedureReturn #False
 EndIf
 If IsImage(*object\image)
  FreeImage(*object\image)
 EndIf
 FreeMemory(*object\srcMem)
 *object\image = imgId
 *object\width = width
 *object\height = height
 *dest = *destMem
 For y = 0 To height - 1
  For x = 0 To width - 1
   For channel = 0 To #IF_UsedChannels - 1
    int = Int(houghField(x, y, channel) / maxValue(channel) * 255)
    limit(int, 0, $FF)
    *dest\channel[channel] = int
   Next channel
   *dest + SizeOf(ImageFilter_RGBA)
  Next x
 Next y
 *object\srcMem = *destMem
 ProcedureReturn #True
EndProcedure


Procedure.i ImageFilter_threshold(*this.IImageFilter, value.i, keepColor.i = #False)
 Protected *object.OImageFilter, gray.i, *src.ImageFilter_RGBA
 If *this = #Null
  ProcedureReturn #False
 EndIf
 *object = *this
 *src = *object\srcMem
 If keepColor
  For i = 0 To *object\pixels - 1
   gray = Gray(*src\rgba)
   If gray < value
    *src\rgba = $000000
   Else
    *src\rgba = RGB(gray, gray, gray)
   EndIf
   *src + SizeOf(ImageFilter_RGBA)
  Next i
 Else
  For i = 0 To *object\pixels - 1
   gray = Gray(*src\rgba)
   If gray < value
    *src\rgba = $000000
   Else
    *src\rgba = $FFFFFF
   EndIf
   *src + SizeOf(ImageFilter_RGBA)
  Next i
 EndIf
 ProcedureReturn #True
EndProcedure


Procedure.i ImageFilter_regionGrowing(*this.IImageFilter, x.i, y.i, maxDelta.i)
 Protected *object.OImageFilter, rgb.ImageFilter_RGBA, *src.ImageFilter_RGBA
 Protected *maskMem.ImageFilter_RGBA, *mask.ImageFilter_RGBA
 Protected c1.ImageFilter_RGBA, c2.ImageFilter_RGBA
 Protected NewList stack.POINT()
 If *this = #Null Or x < 0 Or y < 0 Or maxDelta < 0 Or maxDelta > $FF
  ProcedureReturn #False
 EndIf
 *object = *this
 If x >= *object\width Or y >= *object\height
  ProcedureReturn #False
 EndIf
 *maskMem = AllocateMemory(*object\pixels * SizeOf(ImageFilter_RGBA))
 If *maskMem = 0
  ProcedureReturn #False
 EndIf
 y = *object\height - y - 1
 AddElement(stack())
 stack()\x = x
 stack()\y = y
 setColorFromArray(*maskMem, x, y, *object\width, $FFFFFF)
 While ListSize(stack()) > 0
  FirstElement(stack())
  sx = stack()\x
  sy = stack()\y
  DeleteElement(stack())
  For yi = sy - 1 To sy + 1
   If yi >= 0 And yi < *object\height
    For xi = sx - 1 To sx + 1
     If xi >= 0 And xi < *object\width
      For yb = yi - 1 To yi + 1
       If yb >= 0 And yb < *object\height
        For xb = xi - 1 To xi + 1
         If xb >= 0 And xb < *object\width
          If getColorFromArray(*maskMem, xb, yb, *object\width) <> 0 And getColorFromArray(*maskMem, xi, yi, *object\width) = 0
           delta = 0
           c1\rgba = getColorFromArray(*object\srcMem, xb, yb, *object\width)
           c2\rgba = getColorFromArray(*object\srcMem, xi, yi, *object\width)
           If Abs(Red(c1\rgba) - Red(c2\rgba)) + Abs(Green(c1\rgba) - Green(c2\rgba)) + Abs(Blue(c1\rgba) - Blue(c2\rgba)) <= maxDelta
            AddElement(stack())
            stack()\x = xi
            stack()\y = yi
            setColorFromArray(*maskMem, xi, yi, *object\width, $FFFFFF)
            Break 2
           EndIf
          EndIf
         EndIf
        Next xb
       EndIf
      Next yb
     EndIf
    Next xi
   EndIf
  Next yi
 Wend
 FreeMemory(*object\srcMem)
 *object\srcMem = *maskMem
 ProcedureReturn #True
EndProcedure


Procedure.i ImageFilter_dilate(*this.IImageFilter, label.i, mask$, times.i)
 Protected *object.OImageFilter, *destMem.ImageFilter_RGBA
 Protected maskWidth.i, maskHeight.i, maskValues.i
 Protected maskOffsetX.i, maskOffsetY.i
 Protected oldValue.i, maskValue.i
 Protected continueFor.i
 Protected modified.i = #False
 If *this = #Null Or times < 1 Or mask$ = ""
  ProcedureReturn #False
 EndIf
 *object = *this
 maskWidth = CountString(StringField(mask$, 1, "|"), ",") + 1
 maskHeight = CountString(mask$, "|") + 1
 Protected Dim mask.i((maskWidth * maskHeight) - 1)
 maskValues = 0
 For x = 0 To maskWidth - 1
  For y = 0 To maskHeight - 1
   If Val(Trim(StringField(StringField(mask$, y + 1, "|"), x + 1, ",")))
    mask(maskValues) = ((y - (maskHeight / 2)) * *object\width) + x - (maskWidth / 2)
    maskValues + 1
   EndIf
  Next
 Next
 maskOffsetX = maskWidth >> 1
 maskOffsetY = maskHeight >> 1
 *destMem = AllocateMemory(*object\pixels * SizeOf(ImageFilter_RGBA))
 If *destMem = 0
  ProcedureReturn #False
 EndIf
 For t = 1 To times
  CopyMemory(*object\srcMem, *destMem, *object\pixels * SizeOf(ImageFilter_RGBA))
  For x = maskOffsetX To *object\width - maskOffsetX - 1
   For y = maskOffsetY To *object\height - maskOffsetY - 1
    oldValue = getColorFromArray(*object\srcMem, x, y, *object\width)
    continueFor = #False
    For i = 0 To maskValues - 1
     maskValue = getColorFromArray(*object\srcMem, x + mask(i), y, *object\width)
     If maskValue = label
      If oldValue <> label
       setColorFromArray(*destMem, x, y, *object\width, label)
       modified = #True
      EndIf
      continueFor = #True
      Break 1
     EndIf
    Next i
    If oldValue = label And continueFor = #False
     setColorFromArray(*destMem, x, y, *object\width, $FFFFFF ! label)
     modified = #True
    EndIf
   Next y
  Next x
  Swap *destMem, *object\srcMem
 Next t
 FreeMemory(*destMem)
 ProcedureReturn modified
EndProcedure


Procedure.i ImageFilter_erode(*this.IImageFilter, label.i, mask$, times.i)
 Protected *object.OImageFilter, *destMem.ImageFilter_RGBA
 Protected maskWidth.i, maskHeight.i, maskValues.i
 Protected maskOffsetX.i, maskOffsetY.i
 Protected oldValue.i, maskValue.i
 Protected continueFor.i
 Protected modified.i = #False
 If *this = #Null Or times < 1 Or mask$ = ""
  ProcedureReturn #False
 EndIf
 *object = *this
 maskWidth = CountString(StringField(mask$, 1, "|"), ",") + 1
 maskHeight = CountString(mask$, "|") + 1
 Protected Dim mask.i((maskWidth * maskHeight) - 1)
 maskValues = 0
 For x = 0 To maskWidth - 1
  For y = 0 To maskHeight - 1
   If Val(Trim(StringField(StringField(mask$, y + 1, "|"), x + 1, ",")))
    mask(maskValues) = ((y - (maskHeight / 2)) * *object\width) + x - (maskWidth / 2)
    maskValues + 1
   EndIf
  Next
 Next
 maskOffsetX = maskWidth >> 1
 maskOffsetY = maskHeight >> 1
 *destMem = AllocateMemory(*object\pixels * SizeOf(ImageFilter_RGBA))
 If *destMem = 0
  ProcedureReturn #False
 EndIf
 For t = 1 To times
  CopyMemory(*object\srcMem, *destMem, *object\pixels * SizeOf(ImageFilter_RGBA))
  For x = maskOffsetX To *object\width - maskOffsetX - 1
   For y = maskOffsetY To *object\height - maskOffsetY - 1
    oldValue = getColorFromArray(*object\srcMem, x, y, *object\width)
    continueFor = #False
    For i = 0 To maskValues - 1
     maskValue = getColorFromArray(*object\srcMem, x + mask(i), y, *object\width)
     If maskValue <> label
      If oldValue = label
       setColorFromArray(*destMem, x, y, *object\width, $FFFFFF ! label)
       modified = #True
      EndIf
      continueFor = #True
      Break 1
     EndIf
    Next i
    If oldValue = label And continueFor = #False
     setColorFromArray(*destMem, x, y, *object\width, label)
     modified = #True
    EndIf
   Next y
  Next x
  Swap *destMem, *object\srcMem
 Next t
 FreeMemory(*destMem)
 ProcedureReturn modified
EndProcedure


Procedure.i ImageFilter_closing(*this.IImageFilter, label.i, mask$, times.i)
 Protected *object.OImageFilter, *destMem.ImageFilter_RGBA
 Protected maskWidth.i, maskHeight.i, maskValues.i
 Protected maskOffsetX.i, maskOffsetY.i
 Protected oldValue.i, maskValue.i
 Protected continueFor.i
 Protected modified.i = #False
 If *this = #Null Or times < 1 Or mask$ = ""
  ProcedureReturn #False
 EndIf
 *object = *this
 maskWidth = CountString(StringField(mask$, 1, "|"), ",") + 1
 maskHeight = CountString(mask$, "|") + 1
 Protected Dim mask.i((maskWidth * maskHeight) - 1)
 maskValues = 0
 For x = 0 To maskWidth - 1
  For y = 0 To maskHeight - 1
   If Val(Trim(StringField(StringField(mask$, y + 1, "|"), x + 1, ",")))
    mask(maskValues) = ((y - (maskHeight / 2)) * *object\width) + x - (maskWidth / 2)
    maskValues + 1
   EndIf
  Next
 Next
 maskOffsetX = maskWidth >> 1
 maskOffsetY = maskHeight >> 1
 *destMem = AllocateMemory(*object\pixels * SizeOf(ImageFilter_RGBA))
 If *destMem = 0
  ProcedureReturn #False
 EndIf
 For t = 1 To times
  CopyMemory(*object\srcMem, *destMem, *object\pixels * SizeOf(ImageFilter_RGBA))
  For x = maskOffsetX To *object\width - maskOffsetX - 1
   For y = maskOffsetY To *object\height - maskOffsetY - 1
    oldValue = getColorFromArray(*object\srcMem, x, y, *object\width)
    continueFor = #False
    For i = 0 To maskValues - 1
     maskValue = getColorFromArray(*object\srcMem, x + mask(i), y, *object\width)
     If maskValue = label
      If oldValue <> label
       setColorFromArray(*destMem, x, y, *object\width, label)
       modified = #True
      EndIf
      continueFor = #True
      Break 1
     EndIf
    Next i
    If oldValue = label And continueFor = #False
     setColorFromArray(*destMem, x, y, *object\width, $FFFFFF ! label)
     modified = #True
    EndIf
   Next y
  Next x
  Swap *destMem, *object\srcMem
 Next t
 For t = 1 To times
  CopyMemory(*object\srcMem, *destMem, *object\pixels * SizeOf(ImageFilter_RGBA))
  For x = maskOffsetX To *object\width - maskOffsetX - 1
   For y = maskOffsetY To *object\height - maskOffsetY - 1
    oldValue = getColorFromArray(*object\srcMem, x, y, *object\width)
    continueFor = #False
    For i = 0 To maskValues - 1
     maskValue = getColorFromArray(*object\srcMem, x + mask(i), y, *object\width)
     If maskValue <> label
      If oldValue = label
       setColorFromArray(*destMem, x, y, *object\width, $FFFFFF ! label)
       modified = #True
      EndIf
      continueFor = #True
      Break 1
     EndIf
    Next i
    If oldValue = label And continueFor = #False
     setColorFromArray(*destMem, x, y, *object\width, label)
     modified = #True
    EndIf
   Next y
  Next x
  Swap *destMem, *object\srcMem
 Next t
 FreeMemory(*destMem)
 ProcedureReturn modified
EndProcedure


Procedure.i ImageFilter_opening(*this.IImageFilter, label.i, mask$, times.i)
 Protected *object.OImageFilter, *destMem.ImageFilter_RGBA
 Protected maskWidth.i, maskHeight.i, maskValues.i
 Protected maskOffsetX.i, maskOffsetY.i
 Protected oldValue.i, maskValue.i
 Protected continueFor.i
 Protected modified.i = #False
 If *this = #Null Or times < 1 Or mask$ = ""
  ProcedureReturn #False
 EndIf
 *object = *this
 maskWidth = CountString(StringField(mask$, 1, "|"), ",") + 1
 maskHeight = CountString(mask$, "|") + 1
 Protected Dim mask.i((maskWidth * maskHeight) - 1)
 maskValues = 0
 For x = 0 To maskWidth - 1
  For y = 0 To maskHeight - 1
   If Val(Trim(StringField(StringField(mask$, y + 1, "|"), x + 1, ",")))
    mask(maskValues) = ((y - (maskHeight / 2)) * *object\width) + x - (maskWidth / 2)
    maskValues + 1
   EndIf
  Next
 Next
 maskOffsetX = maskWidth >> 1
 maskOffsetY = maskHeight >> 1
 *destMem = AllocateMemory(*object\pixels * SizeOf(ImageFilter_RGBA))
 If *destMem = 0
  ProcedureReturn #False
 EndIf
 For t = 1 To times
  CopyMemory(*object\srcMem, *destMem, *object\pixels * SizeOf(ImageFilter_RGBA))
  For x = maskOffsetX To *object\width - maskOffsetX - 1
   For y = maskOffsetY To *object\height - maskOffsetY - 1
    oldValue = getColorFromArray(*object\srcMem, x, y, *object\width)
    continueFor = #False
    For i = 0 To maskValues - 1
     maskValue = getColorFromArray(*object\srcMem, x + mask(i), y, *object\width)
     If maskValue <> label
      If oldValue = label
       setColorFromArray(*destMem, x, y, *object\width, $FFFFFF ! label)
       modified = #True
      EndIf
      continueFor = #True
      Break 1
     EndIf
    Next i
    If oldValue = label And continueFor = #False
     setColorFromArray(*destMem, x, y, *object\width, label)
     modified = #True
    EndIf
   Next y
  Next x
  Swap *destMem, *object\srcMem
 Next t
 For t = 1 To times
  CopyMemory(*object\srcMem, *destMem, *object\pixels * SizeOf(ImageFilter_RGBA))
  For x = maskOffsetX To *object\width - maskOffsetX - 1
   For y = maskOffsetY To *object\height - maskOffsetY - 1
    oldValue = getColorFromArray(*object\srcMem, x, y, *object\width)
    continueFor = #False
    For i = 0 To maskValues - 1
     maskValue = getColorFromArray(*object\srcMem, x + mask(i), y, *object\width)
     If maskValue = label
      If oldValue <> label
       setColorFromArray(*destMem, x, y, *object\width, label)
       modified = #True
      EndIf
      continueFor = #True
      Break 1
     EndIf
    Next i
    If oldValue = label And continueFor = #False
     setColorFromArray(*destMem, x, y, *object\width, $FFFFFF ! label)
     modified = #True
    EndIf
   Next y
  Next x
  Swap *destMem, *object\srcMem
 Next t
 FreeMemory(*destMem)
 ProcedureReturn modified
EndProcedure


Procedure.i ImageFilter_thin(*this.IImageFilter, label.i, times.i)
 Protected *object.OImageFilter, *destMem.ImageFilter_RGBA, *tmpMem.ImageFilter_RGBA
 Protected Dim indexedFilterMask.i(7)
 Protected Dim neighbors.i(7)
 Protected numNeighbors.i, numTransitions.i
 Protected modified.i = #False
 If *this = #Null
  ProcedureReturn #False
 EndIf
 *object = *this
 *destMem = AllocateMemory(*object\pixels * SizeOf(ImageFilter_RGBA))
 If *destMem = 0
  ProcedureReturn #False
 EndIf
 indexedFilterMask(0) = -*object\width
 indexedFilterMask(1) = -*object\width + 1
 indexedFilterMask(2) = 1
 indexedFilterMask(3) = *object\width + 1
 indexedFilterMask(4) = *object\width
 indexedFilterMask(5) = *object\width - 1
 indexedFilterMask(6) = -1
 indexedFilterMask(7) = -*object\width - 1
 For t = 1 To times
  CopyMemory(*object\srcMem, *destMem, *object\pixels * SizeOf(ImageFilter_RGBA))
  For y = 1 To *object\height - 2
   For x = 1 To *object\width - 2
    If getColorFromArray(*object\srcMem, x, y, *object\width) = label
     numNeighbors = 0
     For i = 0 To 7
      If getColorFromArray(*object\srcMem, x + indexedFilterMask(i), y, *object\width) = label
       neighbors(i) = #True
       numNeighbors + 1
      Else
       neighbors(i) = #False
      EndIf
     Next i
     If numNeighbors < 2 Or numNeighbors > 6
      Continue
     EndIf
     numTransitions = 0
     For i = 0 To 7
      If neighbors(i) = #False And neighbors((i + 1) % 8) = #True
       numTransitions + 1
      EndIf
     Next i
     If numTransitions <> 1
      Continue
     EndIf
     If neighbors(0) And neighbors(2) And neighbors(4)
      Continue
     EndIf
     If neighbors(2) And neighbors(4) And neighbors(6)
      Continue
     EndIf
     setColorFromArray(*destMem, x, y, *object\width, $FFFFFF - label)
     modified = #True
    EndIf
   Next x
  Next y
  CopyMemory(*destMem, *object\srcMem, *object\pixels * SizeOf(ImageFilter_RGBA))
  For y = 1 To *object\height - 2
   For x = 1 To *object\width - 2
    If getColorFromArray(*object\srcMem, x, y, *object\width) = label
     numNeighbors = 0
     For i = 0 To 7
      If getColorFromArray(*object\srcMem, x + indexedFilterMask(i), y, *object\width) = label
       neighbors(i) = #True
       numNeighbors + 1
      Else
       neighbors(i) = #False
      EndIf
     Next i
     If numNeighbors < 2 Or numNeighbors > 6
      Continue
     EndIf
     numTransitions = 0
     For i = 0 To 7
      If neighbors(i) = #False And neighbors((i + 1) % 8) = #True
       numTransitions + 1
      EndIf
     Next i
     If numTransitions <> 1
      Continue
     EndIf
     If neighbors(0) And neighbors(2) And neighbors(6)
      Continue
     EndIf
     If neighbors(0) And neighbors(4) And neighbors(6)
      Continue
     EndIf
     setColorFromArray(*destMem, x, y, *object\width, $FFFFFF - label)
     modified = #True
    EndIf
   Next x
  Next y
  *tmpMem = *destMem
  *destMem = *object\srcMem
  *object\srcMem = *tmpMem
 Next t
 FreeMemory(*destMem)
 ProcedureReturn modified
EndProcedure


Procedure.i ImageFilter_skeletonization(*this.IImageFilter, label.i)
 If *this = #Null
  ProcedureReturn #False
 EndIf
 While *this\thin(label, 1) : Wend
 ProcedureReturn #True
EndProcedure


Procedure.i ImageFilter_generic(*this.IImageFilter, filter$)
 Protected *object.OImageFilter, *destMem.ImageFilter_RGBA
 If *this = #Null Or filter$ = ""
  ProcedureReturn #False
 EndIf
 *object = *this
 *destMem = *this\memGeneric(*object\srcMem, filter$)
 If *destMem
  FreeMemory(*object\srcMem)
  *object\srcMem = *destMem
 Else
  ProcedureReturn #False
 EndIf
 ProcedureReturn #True
EndProcedure


Procedure.i ImageFilter_bswap(*this.IImageFilter)
 Protected *object.OImageFilter, gray.i, *src.ImageFilter_RGBA
 If *this = #Null
  ProcedureReturn #False
 EndIf
 *object = *this
 *src = *object\srcMem
 For i = 0 To *object\pixels - 1
  Swap *src\channel[0], *src\channel[3]
  Swap *src\channel[1], *src\channel[2]
  *src + SizeOf(ImageFilter_RGBA)
 Next i
 ProcedureReturn #True
EndProcedure


Procedure.i ImageFilter_output(*this.IImageFilter)
 Protected *object.OImageFilter
 If *this = #Null
  ProcedureReturn #False
 EndIf
 *object = *this
 ProcedureReturn *this\setColorArray(*object\srcMem)
EndProcedure


Procedure ImageFilter_delete(*this.IImageFilter)
 Protected *object.OImageFilter
 If *this = #Null
  ProcedureReturn
 EndIf
 *object = *this
 FreeMemory(*object\srcMem)
 FreeMemory(*object)
EndProcedure


Procedure.i ImageFilter_getColorArray(*this.IImageFilter)
 Protected *object.OImageFilter, *mem.ImageFilter_RGBA, *addr.ImageFilter_RGBA, *src.BYTE, *lineStart.BYTE
 If *this = #Null
  ProcedureReturn #Null
 EndIf
 *object = *this
 *mem = AllocateMemory(*object\pixels * SizeOf(ImageFilter_RGBA))
 If *mem = 0
  ProcedureReturn #Null
 EndIf
 If StartDrawing(ImageOutput(*object\image)) = 0
  FreeMemory(*mem)
  ProcedureReturn #Null
 EndIf
 Select DrawingBufferPixelFormat() & $FF
  Case #PB_PixelFormat_24Bits_RGB
   *src = DrawingBuffer()
   If *src = 0
    FreeMemory(*mem)
    StopDrawing()
    ProcedureReturn #Null
   EndIf
   *addr = *mem
   If DrawingBufferPixelFormat() & #PB_PixelFormat_ReversedY = #PB_PixelFormat_ReversedY
    *src + ((*object\height - 1) * DrawingBufferPitch())
    For y = 0 To *object\height - 1
     *lineStart = *src
     For x = 0 To *object\width - 1
      *addr\channel[0] = *src\b : *src + 1
      *addr\channel[1] = *src\b : *src + 1
      *addr\channel[2] = *src\b : *src + 1
      *addr\channel[3] = $FF
      *addr + SizeOf(ImageFilter_RGBA)
     Next x
     *src = *lineStart - DrawingBufferPitch()
    Next y
   Else   
    For y = 0 To *object\height - 1
     *lineStart = *src
     For x = 0 To *object\width - 1
      *addr\channel[0] = *src\b : *src + 1
      *addr\channel[1] = *src\b : *src + 1
      *addr\channel[2] = *src\b : *src + 1
      *addr\channel[3] = $FF
      *addr + SizeOf(ImageFilter_RGBA)
     Next x
     *src = *lineStart + DrawingBufferPitch()
    Next y
   EndIf
  Case #PB_PixelFormat_24Bits_BGR
   *src = DrawingBuffer()
   If *src = 0
    FreeMemory(*mem)
    StopDrawing()
    ProcedureReturn #Null
   EndIf
   *addr = *mem
   If DrawingBufferPixelFormat() & #PB_PixelFormat_ReversedY = #PB_PixelFormat_ReversedY
    *src + ((*object\height - 1) * DrawingBufferPitch())
    For y = 0 To *object\height - 1
     *lineStart = *src
     For x = 0 To *object\width - 1
      *addr\channel[2] = *src\b : *src + 1
      *addr\channel[1] = *src\b : *src + 1
      *addr\channel[0] = *src\b : *src + 1
      *addr\channel[3] = $FF
      *addr + SizeOf(ImageFilter_RGBA)
     Next x
     *src = *lineStart - DrawingBufferPitch()
    Next y
   Else   
    For y = 0 To *object\height - 1
     *lineStart = *src
     For x = 0 To *object\width - 1
      *addr\channel[2] = *src\b : *src + 1
      *addr\channel[1] = *src\b : *src + 1
      *addr\channel[0] = *src\b : *src + 1
      *addr\channel[3] = 0
      *addr + SizeOf(ImageFilter_RGBA)
     Next x
     *src = *lineStart + DrawingBufferPitch()
    Next y
   EndIf
  Case #PB_PixelFormat_32Bits_RGB
   *src = DrawingBuffer()
   If *src = 0
    FreeMemory(*mem)
    StopDrawing()
    ProcedureReturn #Null
   EndIf
   *addr = *mem
   If DrawingBufferPixelFormat() & #PB_PixelFormat_ReversedY = #PB_PixelFormat_ReversedY
    *src + ((*object\height - 1) * DrawingBufferPitch())
    For y = 0 To *object\height - 1
     *lineStart = *src
     For x = 0 To *object\width - 1
      *addr\channel[0] = *src\b : *src + 1
      *addr\channel[1] = *src\b : *src + 1
      *addr\channel[2] = *src\b : *src + 1
      *addr\channel[3] = *src\b : *src + 1
      *addr + SizeOf(ImageFilter_RGBA)
     Next x
     *src = *lineStart - DrawingBufferPitch()
    Next y
   Else   
    For y = 0 To *object\height - 1
     *lineStart = *src
     For x = 0 To *object\width - 1
      *addr\channel[0] = *src\b : *src + 1
      *addr\channel[1] = *src\b : *src + 1
      *addr\channel[2] = *src\b : *src + 1
      *addr\channel[3] = *src\b : *src + 1
      *addr + SizeOf(ImageFilter_RGBA)
     Next x
     *src = *lineStart + DrawingBufferPitch()
    Next y
   EndIf
  Case #PB_PixelFormat_32Bits_BGR
   *src = DrawingBuffer()
   If *src = 0
    FreeMemory(*mem)
    StopDrawing()
    ProcedureReturn #Null
   EndIf
   *addr = *mem
   If DrawingBufferPixelFormat() & #PB_PixelFormat_ReversedY = #PB_PixelFormat_ReversedY
    *src + ((*object\height - 1) * DrawingBufferPitch())
    For y = 0 To *object\height - 1
     *lineStart = *src
     For x = 0 To *object\width - 1
      *addr\channel[2] = *src\b : *src + 1
      *addr\channel[1] = *src\b : *src + 1
      *addr\channel[0] = *src\b : *src + 1
      *addr\channel[3] = *src\b : *src + 1
      *addr + SizeOf(ImageFilter_RGBA)
     Next x
     *src = *lineStart - DrawingBufferPitch()
    Next y
   Else   
    For y = 0 To *object\height - 1
     *lineStart = *src
     For x = 0 To *object\width - 1
      *addr\channel[2] = *src\b : *src + 1
      *addr\channel[1] = *src\b : *src + 1
      *addr\channel[0] = *src\b : *src + 1
      *addr\channel[3] = *src\b : *src + 1
      *addr + SizeOf(ImageFilter_RGBA)
     Next x
     *src = *lineStart + DrawingBufferPitch()
    Next y
   EndIf
  Default
   *addr = *mem
   If OutputDepth() = 32
    For y = 0 To *object\height - 1
     For x = 0 To *object\width - 1
      *addr\rgba = Point(x, y)
      *addr + SizeOf(ImageFilter_RGBA)
     Next x
    Next y
   Else
    For y = 0 To *object\height - 1
     For x = 0 To *object\width - 1
      *addr\rgba = Point(x, y)
      *addr\channel[3] = $FF
      *addr + SizeOf(ImageFilter_RGBA)
     Next x
    Next y
   EndIf
  EndSelect
 StopDrawing()
 ProcedureReturn *mem
EndProcedure


Procedure.i ImageFilter_setColorArray(*this.IImageFilter, *mem.ImageFilter_RGBA)
 Protected *object.OImageFilter, *addr.ImageFilter_RGBA, *dest.BYTE, *lineStart.BYTE
 If *this = #Null Or *mem = #Null
  ProcedureReturn #False
 EndIf
 *object = *this
 If StartDrawing(ImageOutput(*object\image)) = 0
  ProcedureReturn #False
 EndIf
 Select DrawingBufferPixelFormat() & $FF
  Case #PB_PixelFormat_24Bits_RGB
   *dest = DrawingBuffer()
   If *dest = 0
    StopDrawing()
    ProcedureReturn #False
   EndIf
   *addr = *mem
   If DrawingBufferPixelFormat() & #PB_PixelFormat_ReversedY = #PB_PixelFormat_ReversedY
    *dest + ((*object\height - 1) * DrawingBufferPitch())
    For y = 0 To *object\height - 1
     *lineStart = *dest
     For x = 0 To *object\width - 1
      *dest\b = *addr\channel[0] : *dest + 1
      *dest\b = *addr\channel[1] : *dest + 1
      *dest\b = *addr\channel[2] : *dest + 1
      *addr + SizeOf(ImageFilter_RGBA)
     Next x
     *dest = *lineStart - DrawingBufferPitch()
    Next y
   Else
    For y = 0 To *object\height - 1
     *lineStart = *dest
     For x = 0 To *object\width - 1
      *dest\b = *addr\channel[0] : *dest + 1
      *dest\b = *addr\channel[1] : *dest + 1
      *dest\b = *addr\channel[2] : *dest + 1
      *addr + SizeOf(ImageFilter_RGBA)
     Next x
     *dest = *lineStart + DrawingBufferPitch()
    Next y
   EndIf
  Case #PB_PixelFormat_24Bits_BGR
   *dest = DrawingBuffer()
   If *dest = 0
    StopDrawing()
    ProcedureReturn #False
   EndIf
   *addr = *mem
   If DrawingBufferPixelFormat() & #PB_PixelFormat_ReversedY = #PB_PixelFormat_ReversedY
    *dest + ((*object\height - 1) * DrawingBufferPitch())
    For y = 0 To *object\height - 1
     *lineStart = *dest
     For x = 0 To *object\width - 1
      *dest\b = *addr\channel[2] : *dest + 1
      *dest\b = *addr\channel[1] : *dest + 1
      *dest\b = *addr\channel[0] : *dest + 1
      *addr + SizeOf(ImageFilter_RGBA)
     Next x
     *dest = *lineStart - DrawingBufferPitch()
    Next y
   Else
    For y = 0 To *object\height - 1
     *lineStart = *dest
     For x = 0 To *object\width - 1
      *dest\b = *addr\channel[2] & $FF : *dest + 1
      *dest\b = *addr\channel[1] & $FF : *dest + 1
      *dest\b = *addr\channel[0] & $FF : *dest + 1
      *addr + SizeOf(ImageFilter_RGBA)
     Next x
     *dest = *lineStart + DrawingBufferPitch()
    Next y
   EndIf
  Case #PB_PixelFormat_32Bits_RGB
   *dest = DrawingBuffer()
   If *dest = 0
    StopDrawing()
    ProcedureReturn #False
   EndIf
   *addr = *mem
   If DrawingBufferPixelFormat() & #PB_PixelFormat_ReversedY = #PB_PixelFormat_ReversedY
    *dest + ((*object\height - 1) * DrawingBufferPitch())
    For y = 0 To *object\height - 1
     *lineStart = *dest
     For x = 0 To *object\width - 1
      *dest\b = *addr\channel[0] : *dest + 1
      *dest\b = *addr\channel[1] : *dest + 1
      *dest\b = *addr\channel[2] : *dest + 1
      *dest\b = *addr\channel[3] : *dest + 1
      *addr + SizeOf(ImageFilter_RGBA)
     Next x
     *dest = *lineStart - DrawingBufferPitch()
    Next y
   Else
    For y = 0 To *object\height - 1
     *lineStart = *dest
     For x = 0 To *object\width - 1
      *dest\b = *addr\channel[0] & $FF : *dest + 1
      *dest\b = *addr\channel[1] & $FF : *dest + 1
      *dest\b = *addr\channel[2] & $FF : *dest + 1
      *dest\b = *addr\channel[3] & $FF : *dest + 1
      *addr + SizeOf(ImageFilter_RGBA)
     Next x
     *dest = *lineStart + DrawingBufferPitch()
    Next y
   EndIf
  Case #PB_PixelFormat_32Bits_BGR
   *dest = DrawingBuffer()
   If *dest = 0
    StopDrawing()
    ProcedureReturn #False
   EndIf
   *addr = *mem
   If DrawingBufferPixelFormat() & #PB_PixelFormat_ReversedY = #PB_PixelFormat_ReversedY
    *dest + ((*object\height - 1) * DrawingBufferPitch())
    For y = 0 To *object\height - 1
     *lineStart = *dest
     For x = 0 To *object\width - 1
      *dest\b = *addr\channel[2] : *dest + 1
      *dest\b = *addr\channel[1] : *dest + 1
      *dest\b = *addr\channel[0] : *dest + 1
      *dest\b = *addr\channel[3] : *dest + 1
      *addr + SizeOf(ImageFilter_RGBA)
     Next x
     *dest = *lineStart - DrawingBufferPitch()
    Next y
   Else
    For y = 0 To *object\height - 1
     *lineStart = *dest
     For x = 0 To *object\width - 1
      *dest\b = *addr\channel[2] & $FF : *dest + 1
      *dest\b = *addr\channel[1] & $FF : *dest + 1
      *dest\b = *addr\channel[0] & $FF : *dest + 1
      *dest\b = *addr\channel[3] & $FF : *dest + 1
      *addr + SizeOf(ImageFilter_RGBA)
     Next x
     *dest = *lineStart + DrawingBufferPitch()
    Next y
   EndIf
  Default
   *addr = *mem
   If OutputDepth() = 32
    DrawingMode(#PB_2DDrawing_AlphaChannel)
    Box(0, 0, *object\width, *object\height, $00000000)
    DrawingMode(#PB_2DDrawing_AlphaBlend)
   EndIf
   For y = 0 To *object\height - 1
    For x = 0 To *object\width - 1
     Plot(x, y, *addr\rgba)
     *addr + SizeOf(ImageFilter_RGBA)
    Next x
   Next y
  EndSelect
 StopDrawing()
 ProcedureReturn #True
EndProcedure


Procedure.i ImageFilter_memBinomial(*this.IImageFilter, *mem.ImageFilter_RGBA, size.i)
 Protected *object.OImageFilter, src1.ImageFilter_RGBA, src2.ImageFilter_RGBA, *srcMem.ImageFilter_RGBA, *destMem.ImageFilter_RGBA
 Protected int.i, offset.i
 If *this = #Null Or *mem = #Null
  ProcedureReturn #Null
 EndIf
 *object = *this
 *srcMem = AllocateMemory(*object\pixels * SizeOf(ImageFilter_RGBA))
 If *srcMem = #Null
  ProcedureReturn #Null
 EndIf
 If size < 2
  CopyMemory(*mem, *srcMem, *object\pixels * SizeOf(ImageFilter_RGBA))
  ProcedureReturn *srcMem
 EndIf
 *destMem = AllocateMemory(*object\pixels * SizeOf(ImageFilter_RGBA))
 If *destMem = #Null
  ProcedureReturn #Null
 EndIf
 CopyMemory(*mem, *srcMem, *object\pixels * SizeOf(ImageFilter_RGBA))
 offset = 1
 For p = 2 To size
  For y = 0 To *object\height - 1
   For x = offset To *object\width - 2 + offset
    src1\rgba = getColorFromArray(*srcMem, x - offset, y, *object\width)
    src2\rgba = getColorFromArray(*srcMem, x + 1 - offset, y, *object\width)
    For channel = 0 To #IF_UsedChannels - 1
     int = (src1\channel[channel] & $FF) + (src2\channel[channel] & $FF)
     src1\channel[channel] = Int(int / 2)
    Next channel
    setColorFromArray(*destMem, x, y, *object\width, src1\rgba)
   Next x
   If offset = 0
    src1\rgba = getColorFromArray(*srcMem, *object\width - 1, y, *object\width)
    setColorFromArray(*destMem, *object\width - 1, y, *object\width, src1\rgba)
   Else
    src1\rgba = getColorFromArray(*srcMem, 0, y, *object\width)
    setColorFromArray(*destMem, 0, y, *object\width, src1\rgba)
   EndIf
  Next y
  For x = 0 To *object\width - 1
   For y = offset To *object\height - 2 + offset
    src1\rgba = getColorFromArray(*destMem, x, y - offset, *object\width)
    src2\rgba = getColorFromArray(*destMem, x, y + 1 - offset, *object\width)
    For channel = 0 To #IF_UsedChannels - 1
     int = (src1\channel[channel] & $FF) + (src2\channel[channel] & $FF)
     src1\channel[channel] = Int(int / 2)
    Next channel
    setColorFromArray(*srcMem, x, y, *object\width, src1\rgba)
   Next y
   If offset = 0
    src1\rgba = getColorFromArray(*destMem, x, *object\height - 1, *object\width)
    setColorFromArray(*srcMem, x, *object\height - 1, *object\width, src1\rgba)
   Else
    src1\rgba = getColorFromArray(*destMem, x, 0, *object\width)
    setColorFromArray(*srcMem, x, 0, *object\width, src1\rgba)
   EndIf
  Next x
  offset = 1 - offset
 Next
 FreeMemory(*destMem)
 ProcedureReturn *srcMem
EndProcedure


Procedure.i ImageFilter_memGeneric(*this.IImageFilter, *srcMem.ImageFilter_RGBA,filter$)
 Protected *object.OImageFilter, *destMem.ImageFilter_RGBA
 Protected src.ImageFilter_RGBA, dest.ImageFilter_RGBA, curColor.i
 Protected filterWidth.i, filterHeight.i, filterOffsetX.i, filterOffsetY.i
 Protected filterMatrix$, divide.f, offset.f
 Protected newValue.f
 If *this = #Null Or *srcMem = #Null
  ProcedureReturn #Null
 EndIf
 *object = *this
 *destMem = AllocateMemory(*object\pixels * SizeOf(ImageFilter_RGBA))
 If *destMem = #Null
  ProcedureReturn #Null
 EndIf
 CopyMemory(*srcMem, *destMem, *object\pixels * SizeOf(ImageFilter_RGBA))
 filterMatrix$ = Trim(StringField(filter$, 1, ";"))
 divide = ValF(Trim(StringField(filter$, 2, ";")))
 offset = ValF(Trim(StringField(filter$, 3, ";")))
 filterWidth = CountString(StringField(filterMatrix$, 1, "|"), ",") + 1
 filterHeight = CountString(filterMatrix$, "|") + 1
 Protected Dim filter.f(filterWidth - 1, filterHeight - 1)
 For x = 0 To filterWidth - 1
  For y = 0 To filterHeight - 1
   filter(x, y) = ValF(Trim(StringField(StringField(filterMatrix$, y + 1, "|"), x + 1, ",")))
  Next
 Next
 filterOffsetX = filterWidth >> 1
 filterOffsetY = filterHeight >> 1
 For x = filterOffsetX To *object\width - filterOffsetX - 1
  For y = filterOffsetY To *object\height - filterOffsetY - 1
   For channel = 0 To #IF_UsedChannels - 1
    newValue = 0
    For xi = x - filterOffsetX To x + filterOffsetX
     For yi = y - filterOffsetY To y + filterOffsetY
      src\rgba = getColorFromArray(*srcMem, xi, yi, *object\width)
      curColor = src\channel[channel] & $FF
      newValue = newValue + (curColor * filter(xi - x + filterOffsetX, yi - y + filterOffsetY))
     Next yi
    Next xi
     newValue = (newValue / divide) + offset
     limit(newValue, 0, 255)
     dest\channel[channel] = newValue
   Next channel
   setColorFromArray(*destMem, x, y, *object\width, dest\rgba)
  Next y
 Next x
 ProcedureReturn *destMem
EndProcedure


; ;########################################
; UseJPEGImageDecoder()
;
; img = LoadImage(#PB_Any, "D:\Downloads\Backgrounds\getme.jpg")
;
; filter1.IImageFilter = newImageFilter(img)
; filter2.IImageFilter = newImageFilter(img)
; filter3.IImageFilter = newImageFilter(img)
;
; filter1\median(1)
; filter1\generic("1,2,1|0,0,0|-1,-2,-1;8;128")
;
; filter2\median(1)
; filter2\generic("1,0,-1|2,0,-2|1,0,-1;8;128")
; filter2\euclidianNorm(filter1, 0)
; filter2\invert()
; filter2\grayscale()
;
; filter3\median(1)
; filter3\weight(filter2, 1, -128)
; filter3\median(1)
; filter3\output()
;
; filter1\delete()
; filter2\delete()
; filter3\delete()
;
; OpenWindow(0, 0, 0, ImageWidth(img), ImageHeight(img), "CImageFilter", #PB_Window_SystemMenu | #PB_Window_MinimizeGadget | #PB_Window_ScreenCentered)
; ImageGadget(0, 0, 0, ImageWidth(img), ImageHeight(img), ImageID(img))
; Repeat : Until WaitWindowEvent() = #PB_Event_CloseWindow


Top
 Profile  
 
 Post subject: Re: class for image manipulation (OOP)
PostPosted: Sat Apr 14, 2012 12:11 am 
Offline
Addict
Addict
User avatar

Joined: Fri Sep 21, 2007 5:52 am
Posts: 2485
Location: New Zealand
very useful thanks.


Top
 Profile  
 
 Post subject: Re: class for image manipulation (OOP)
PostPosted: Sat Apr 14, 2012 10:48 am 
Offline
Enthusiast
Enthusiast
User avatar

Joined: Sun Oct 31, 2004 10:54 am
Posts: 511
hi ,

with the example code:

Code:
; ;########################################
 UseJPEGImageDecoder()
;
file$=OpenFileRequester("ouvrir un jpg","e:\","images|*.jpg",0)
img = LoadImage(#PB_Any, file$)

filter1.IImageFilter = newImageFilter(img)
filter2.IImageFilter = newImageFilter(img)
filter3.IImageFilter = newImageFilter(img)

filter1\median(1)
filter1\generic("1,2,1|0,0,0|-1,-2,-1;8;128")

filter2\median(1)
filter2\generic("1,0,-1|2,0,-2|1,0,-1;8;128")
filter2\euclidianNorm(filter1, 0)
filter2\invert()
filter2\grayscale()

filter3\median(1)
filter3\weight(filter2, 1, -128)
filter3\median(1)
filter3\output()

filter1\delete()
filter2\delete()
filter3\delete()

Enumeration
#window
#gadget_image
EndEnumeration

OpenWindow(#window, 0, 0, ImageWidth(img), ImageHeight(img), "CImageFilter", #PB_Window_SystemMenu | #PB_Window_MinimizeGadget | #PB_Window_ScreenCentered)
ImageGadget(#gadget_image, 0, 0, ImageWidth(img), ImageHeight(img), ImageID(img))
Repeat : Until WaitWindowEvent() = #PB_Event_CloseWindow
; ***************************************************************************


and this picture
http://michel.dobro.free.fr/Forum_pb/Image17.jpg


I get an error line 243: (filter2\median(1) )
Quote:
"Invalid memory access (read error at address 0)"
Quote:
" Acces memoire invalide (erreur de lecture a l'adresse 0 ")



:cry:

_________________
Image
************************************
site : http://michel.dobro.free.fr/
Videos : http://www.youtube.com/user/DobroMG
************************************


Top
 Profile  
 
 Post subject: Re: class for image manipulation (OOP)
PostPosted: Sun Apr 15, 2012 12:32 pm 
Offline
User
User
User avatar

Joined: Sat May 22, 2004 1:38 am
Posts: 69
Way too old code.. seems the example was broken ;)
Code:
;########################################
 UseJPEGImageDecoder()
;
file$=OpenFileRequester("ouvrir un jpg","e:\","images|*.jpg",0)
img1 = LoadImage(#PB_Any, file$)
img2 = CopyImage(img1, #PB_Any)
img3 = CopyImage(img1, #PB_Any)

filter1.IImageFilter = newImageFilter(img1)
img1 = filter1\getImage() ; image was adjusted to a different color depth
filter2.IImageFilter = newImageFilter(img2)
img2 = filter2\getImage() ; image was adjusted to a different color depth
filter3.IImageFilter = newImageFilter(img3)
img3 = filter3\getImage() ; image was adjusted to a different color depth

filter1\median(1)
filter1\generic("1,2,1|0,0,0|-1,-2,-1;8;128")

filter2\median(1)
filter2\generic("1,0,-1|2,0,-2|1,0,-1;8;128")
filter2\euclidianNorm(filter1, 0)
filter2\invert()
filter2\grayscale()

filter3\median(1)
filter3\weight(filter2, 1, -128)
filter3\median(1)
filter3\output()

filter1\delete()
filter2\delete()
filter3\delete()

FreeImage(img1)
FreeImage(img2)

Enumeration
#window
#gadget_image
EndEnumeration

OpenWindow(#window, 0, 0, ImageWidth(img3), ImageHeight(img3), "CImageFilter", #PB_Window_SystemMenu | #PB_Window_MinimizeGadget | #PB_Window_ScreenCentered)
ImageGadget(#gadget_image, 0, 0, ImageWidth(img3), ImageHeight(img3), ImageID(img3))
Repeat : Until WaitWindowEvent() = #PB_Event_CloseWindow
; ***************************************************************************


Well I did quite a couple of adjustments when I used it for a scripting interpreter back then.

CHashTableS.pbi
Code:
Prototype.i HashFunctionS(key$, limit.i)

Interface IHashTableS
 addKey(key$)   ;return pointer to data memory
 getKey(key$)   ;return pointer to data memory
 delKey(key$)   ;return pointer to data memory which has been deleted
 size()         ;return number of elments in the hash table
 clear()        ;remove all elements in the hash table
 ;hash function
 getHashFunction() ;returns the address of the hash function
 setHashFunction(hash.HashFunctionS) ;returns the old hash function or #Null if failed
 ;free object
 delete()
EndInterface

Structure EHashTableS
 *after.EHashTableS
 key.s
EndStructure

Structure OHashTableS
 ;Address to the methods array
 methodAddress.i
 ;Class Attributes
  ;Constants
  elementSize.i
  tableSize.i
  ;Variables
  size.i
  table.i
  hash.HashFunctionS
EndStructure


Declare.i newHashTableS(dataSize.i, tableSize.i)
Declare.i HashTableS_addKey(*this.IHashTableS, key$)
Declare.i HashTableS_getKey(*this.IHashTableS, key$)
Declare.i HashTableS_delKey(*this.IHashTableS, key$)
Declare.i HashTableS_size(*this.IHashTableS)
Declare.i HashTableS_clear(*this.IHashTableS)
Declare.i HashTableS_getHashFunction(*this.IHashTableS)
Declare.i HashTableS_setHashFunction(*this.IHashTableS, hash.HashFunctionS)
Declare   HashTableS_delete(*this.IHashTableS)

Declare.i HashTableS_defaultHashFunction(key$, limit.i)


DataSection
 OHashTableS_methods:
  Data.i @HashTableS_addKey()
  Data.i @HashTableS_getKey()
  Data.i @HashTableS_delKey()
  Data.i @HashTableS_size()
  Data.i @HashTableS_clear()
  Data.i @HashTableS_getHashFunction()
  Data.i @HashTableS_setHashFunction()
  Data.i @HashTableS_delete()
EndDataSection


Procedure.i newHashTableS(dataSize.i, tableSize.i)
 Protected *object.OHashTableS
 *object = AllocateMemory(SizeOf(OHashTableS))
 If *object = #Null
  ProcedureReturn #Null
 EndIf
 *object\methodAddress = ?OHashTableS_methods
 *object\elementSize = SizeOf(EHashTableS) + dataSize
 *object\tableSize = tableSize
 *object\size    = 0
 *object\table   = AllocateMemory(SizeOf(INTEGER) * tableSize)
 *object\hash    = @HashTableS_defaultHashFunction()
 If *object\table = #Null
  FreeMemory(*object)
  ProcedureReturn #Null
 EndIf
 ProcedureReturn *object
EndProcedure


Procedure.i HashTableS_addKey(*this.IHashTableS, key$)
 Protected *object.OHashTableS, *element.EHashTableS, *nextElement.EHashTableS
 Protected tablePosition.i
 If *this = #Null Or key$ = ""
  ProcedureReturn #Null
 EndIf
 *object = *this
 *element = *this\getKey(key$)
 If *element
  ProcedureReturn *element
 EndIf
 *element = AllocateMemory(*object\elementSize)
 If *element = #Null
  ProcedureReturn #Null
 EndIf
 *element\after = #Null
 *element\key = key$
 tablePosition = SizeOf(INTEGER) * *object\hash(key$, *object\tableSize)
 *nextElement = PeekI(*object\table + tablePosition)
 If *nextElement = #Null
  PokeI(*object\table + tablePosition, *element)
 Else
  While *nextElement\after
   *nextElement = *nextElement\after
  Wend
  *nextElement\after = *element
 EndIf
 *object\size + 1
 ProcedureReturn *element + SizeOf(EHashTableS)
EndProcedure


Procedure.i HashTableS_getKey(*this.IHashTableS, key$)
 Protected *object.OHashTableS, *nextElement.EHashTableS
 Protected tablePosition.i
 If *this = #Null Or key$ = ""
  ProcedureReturn #Null
 EndIf
 *object = *this
 tablePosition = SizeOf(INTEGER) * *object\hash(key$, *object\tableSize)
 *nextElement = PeekI(*object\table + tablePosition)
 If *nextElement
  While *nextElement\after And *nextElement\key <> key$
   *nextElement = *nextElement\after
  Wend
  If *nextElement\key = key$
   ProcedureReturn *nextElement + SizeOf(EHashTableS)
  EndIf
 EndIf
 ProcedureReturn #Null
EndProcedure


Procedure.i HashTableS_delKey(*this.IHashTableS, key$)
 Protected *object.OHashTableS, *lastElement.EHashTableS, *nextElement.EHashTableS
 Protected tablePosition.i
 If *this = #Null Or key$ = ""
  ProcedureReturn #Null
 EndIf
 *object = *this
 tablePosition = SizeOf(INTEGER) * *object\hash(key$, *object\tableSize)
 *nextElement = PeekI(*object\table + tablePosition)
 If *nextElement
  If *nextElement\key = key$
   PokeI(*object\table + tablePosition, *nextElement\after)
   FreeMemory(*nextElement)
   *object\size - 1
   ProcedureReturn *nextElement + SizeOf(EHashTableS)
  Else
   While *nextElement\after And *nextElement\key <> key$
    *lastElement = *nextElement
    *nextElement = *nextElement\after
   Wend
   If *nextElement\key = key$
    *lastElement\after = *nextElement\after
    FreeMemory(*nextElement)
    *object\size - 1
    ProcedureReturn *nextElement + SizeOf(EHashTableS)
   EndIf
  EndIf
 EndIf
 ProcedureReturn #Null
EndProcedure


Procedure.i HashTableS_size(*this.IHashTableS)
 Protected *object.OHashTableS
 If *this = #Null
  ProcedureReturn 0
 EndIf
 *object = *this
 ProcedureReturn *object\size
EndProcedure


Procedure.i HashTableS_clear(*this.IHashTableS)
 Protected *object.OHashTableS, *entry.INTEGER, *element.EHashTableS, *nextElement.EHashTableS
 If *this = #Null
  ProcedureReturn #False
 EndIf
 *object = *this
 *entry = *object\table
 For i = 1 To *object\tableSize
  *nextElement = *entry\i
  If *nextElement
   Repeat
    *element = *nextElement
    *nextElement = *nextElement\after
    FreeMemory(*element)
   Until *nextElement = #Null
  EndIf
  *entry\i = #Null
  *entry + SizeOf(INTEGER)
 Next
 *object\size = 0
 ProcedureReturn #True
EndProcedure


Procedure.i HashTableS_getHashFunction(*this.IHashTableS)
 Protected *object.OHashTableS
 If *this = #Null
  ProcedureReturn #Null
 EndIf
 *object = *this
 ProcedureReturn *object\hash
EndProcedure


Procedure.i HashTableS_setHashFunction(*this.IHashTableS, hash.HashFunctionS)
 Protected *object.OHashTableS
 If *this = #Null Or hash = #Null
  ProcedureReturn #False
 EndIf
 *object = *this
 *object\hash = hash
 ProcedureReturn #True
EndProcedure


Procedure HashTableS_delete(*this.IHashTableS)
 Protected *object.OHashTableS
 If *this = #Null
  ProcedureReturn
 EndIf
 *object = *this
 *this\clear()
 FreeMemory(*object\table)
 FreeMemory(*object)
EndProcedure


Procedure.i HashTableS_defaultHashFunction(key$, limit.i)
 ProcedureReturn (CRC32Fingerprint(@key$, StringByteLength(key$), $00000000) & $7FFFFFFF) % limit
EndProcedure


FilterInterpreter.pb
Code:
XIncludeFile "CImageFilter.pbi"
XIncludeFile "CHashTableS.pbi"

UseJPEG2000ImageDecoder()
UseJPEGImageDecoder()
UsePNGImageDecoder()
UseTGAImageDecoder()
UseTIFFImageDecoder()

UseJPEGImageEncoder()
UsePNGImageEncoder()


;string to type macros
Macro s_(var,  i) : StringField(var + Chr(1), i, Chr(1))            : EndMacro
Macro st_(var, i) : TrimQuote(StringField(var + Chr(1), i, Chr(1))) : EndMacro
Macro i_(var,  i) : Val(StringField(var + Chr(1), i, Chr(1)))       : EndMacro
Macro f_(var,  i) : ValF(StringField(var + Chr(1), i, Chr(1)))      : EndMacro
Macro out_(text = " ") : PrintR("", text) : EndMacro


#MaxImageInstancesPerLine = 3
CompilerIf #PB_Compiler_Unicode
 #P_Version = "1.00 Unicode Beta"
CompilerElse
 #P_Version = "1.00 Ascii Beta"
CompilerEndIf

Structure COMMAND_STRUC
 method.s
 params.s
 line.i
EndStructure

Structure IMAGE_STRUC
 name.s
 file.s
 id.i
 instance.IImageFilter
EndStructure

Structure GARBAGE_STRUC
 nameCount.i
 imgNames.s[#MaxImageInstancesPerLine]
EndStructure

Structure GCINIT_STRUC
 lastLine.i
EndStructure


Global NewList prog.COMMAND_STRUC()
Global images.IHashTableS = newHashTables(SizeOf(IMAGE_STRUC), 100)
Global Dim gc.GARBAGE_STRUC(0)


Declare   PrintR(String$, Line$ = "")
Declare.s TrimQuote(String$)
Declare.i parseLine(Line$, Number.i)
Declare.i GarbageCollectorInit()
Declare.i GarbageCollectorTest(Line.i)
Declare.i NewInstanceOf(namedImage$, file$)
Declare.i CopyInstanceOf(namedImage$, otherNamedImage$)
Declare.i GetInstanceOf(namedImage$)
Declare.i UpdateInstanceOf(namedImage$)
Declare.i FreeInstanceOf(namedImage$)
Declare.i callCommand(command$, params$) ;functions mapping is done here
Declare   ExitProgram()


Procedure PrintR(String$, Line$ = "")
 If Line$
  PrintN(LSet(Line$, 78, " "))
 EndIf
 If String$
  Print(LSet(String$, 78, " ") + Chr(13))
 EndIf
EndProcedure


Procedure.s TrimQuote(String$)
 If Asc(Left(String$, 1)) = '"' And Asc(Right(String$, 1)) = '"'
  ProcedureReturn Mid(String$, 2, Len(String$) - 2)
 EndIf
 ProcedureReturn String$
EndProcedure


Procedure.i parseLine(Line$, Number.i)
 Protected *char.CHARACTER, *finalChar.CHARACTER, isLoad.i, isCommand.i, inString.i
 Protected strLen.i, stringStart.c
 Line$ = Trim(Line$)
 If Line$ = "" Or Left(Line$, 1) = ";"
  ProcedureReturn #True
 EndIf
 *char = @Line$
 *finalChar = *char + (Len(Line$) * SizeOf(CHARACTER))
 isLoad = #False
 isCommand = #False
 inString = #False
 While *char < *finalChar
  If inString
   Select *char\c
    Case stringStart
     If isCommand
      *char\c = '"'
      inString = #False
     EndIf
   EndSelect
  Else
   Select *char\c
    Case '(', '[', '{', '<'
     If isLoad = #False
      If *char <> @Line$
       isCommand = #True
      EndIf
      *char\c = '('
     EndIf
    Case ')', ']', '}', '>'
     If isLoad = #False
      *char\c = ')'
     EndIf
    Case '"', 39 ;'
     If isCommand
      stringStart = *char\c
      *char\c = '"'
      inString = #True
     EndIf
    Case ','
     If isCommand
      *char\c = 1
     EndIf
    Case 9
     *char\c = ' '
    Case '='
     If isCommand = #False
      isLoad = #True
     EndIf
   EndSelect
  EndIf
  *char + SizeOf(CHARACTER)
 Wend
 If LCase(Line$) = "end"
  AddElement(prog())
  prog()\method = "end"
  prog()\params = ""
  prog()\line = Number
 ElseIf isLoad
  AddElement(prog())
  prog()\method = "loadImage"
  prog()\params = Trim(StringField(Line$, 1, "=")) + Chr(1) + Trim(StringField(Line$, 2, "="))
  prog()\line = Number
 ElseIf isCommand
  Repeat
   strLen = Len(Line$)
   Line$ = ReplaceString(Line$, " ", "")
  Until strLen = Len(Line$)
  If Left(Line$, 1) = ";"
   ProcedureReturn #True
  EndIf
  AddElement(prog())
  prog()\method = StringField(Line$, 1, "(")
  prog()\params = StringField(StringField(Line$, 2, "("), 1, ")")
  prog()\line = Number
 Else
  ProcedureReturn #False
 EndIf
 ProcedureReturn #True
EndProcedure


Procedure.i GarbageCollectorInit()
 Protected gcinit.IHashTableS, *element.GCINIT_STRUC
 Protected paramImgCount.i, lineCount.i
 Protected NewList imgNames.s()
 gcinit = newHashTables(SizeOf(GCINIT_STRUC), 100)
 If gcinit = #Null
  ProcedureReturn #False
 EndIf
 LastElement(prog())
 lineCount = prog()\line
 ForEach prog()
  ;-- auto free images - <
  Select LCase(prog()\method)
   Case "end"
    Break
   Case LCase("loadImage")
    If gcinit\getKey(LCase(s_(prog()\params, 2)))
     paramImgCount = 2
    Else
     paramImgCount = 1
    EndIf
   Case "add", "sub", "mul", "div", "xor", "and", "or", "weight", "difference", LCase("euclidianNorm"), LCase("manhattenNorm")
    paramImgCount = 2
   Case LCase("weightMask")
    paramImgCount = 3
   Default
    paramImgCount = 1
  EndSelect
  For i = 1 To paramImgCount
   If LCase(s_(prog()\params, i)) <> "clipboard" And s_(prog()\params, i) <> ""
    If gcinit\getKey(LCase(s_(prog()\params, i))) = #Null
     AddElement(imgNames())
     imgNames() = LCase(s_(prog()\params, i))
    EndIf
    *element = gcinit\addKey(LCase(s_(prog()\params, i)))
    If *element = #Null
     gcinit\delete()
     ProcedureReturn #False
    EndIf
    *element\lastLine = prog()\line
   EndIf
  Next i
 Next
 ReDim gc(lineCount)
 ForEach imgNames()
  *element = gcinit\getKey(imgNames())
  If *element = #Null
   gcinit\delete()
   ProcedureReturn #False
  EndIf
  If *element\lastLine > lineCount
   gcinit\delete()
   ProcedureReturn #False
  EndIf
  If gc(*element\lastLine)\nameCount >= #MaxImageInstancesPerLine
   gcinit\delete()
   ProcedureReturn #False
  EndIf
  gc(*element\lastLine)\imgNames[gc(*element\lastLine)\nameCount] = imgNames()
  gc(*element\lastLine)\nameCount + 1
 Next
 ClearList(imgNames())
 gcinit\delete()
 ProcedureReturn #True
EndProcedure


Procedure.i GarbageCollectorTest(Line.i)
 If gc(Line)\nameCount = 0
  ProcedureReturn #True
 EndIf
 For i = 0 To gc(Line)\nameCount - 1
  FreeInstanceOf(gc(Line)\imgNames[i])
 Next
 ProcedureReturn #True
EndProcedure


Procedure.i NewInstanceOf(namedImage$, file$)
 Protected nameInUse.i = #False, newImage.i, *element.IMAGE_STRUC
 Protected newInstance.IImageFilter
 namedImage$ = LCase(namedImage$)
 If namedImage$ = ""
  ProcedureReturn #False
 EndIf
 If file$ = "clipboard"
  newImage = GetClipboardImage(#PB_Any)
 Else
  newImage = LoadImage(#PB_Any, file$)
 EndIf
 If newImage = #Null
  ProcedureReturn #False
 EndIf
 If namedImage$ = "clipboard"
  SetClipboardImage(newImage)
  FreeImage(newImage)
  ProcedureReturn #True
 EndIf
 newInstance = newImageFilter(newImage)
 If newInstance = #Null
  FreeImage(newImage)
  ProcedureReturn #False
 EndIf
 newImage = newInstance\getImage()
 *element = images\addKey(namedImage$)
 If *element = #Null
  newInstance\delete()
  FreeImage(newImage)
  ProcedureReturn #False
 EndIf
 If IsImage(*element\id)
  FreeImage(*element\id)
  *element\id = #Null
  *element\instance\delete()
  *element\instance = #Null
 EndIf
 *element\name = namedImage$
 *element\file = file$
 *element\id = newImage
 *element\instance = newInstance
 ProcedureReturn #True
EndProcedure


Procedure.i CopyInstanceOf(namedImage$, otherNamedImage$)
 Protected nameInUse.i = #False, *element.IMAGE_STRUC
 Protected newInstance.IImageFilter, otherInstance.IImageFilter
 namedImage$ = LCase(namedImage$)
 otherNamedImage$ = LCase(otherNamedImage$)
 If namedImage$ = "" Or otherNamedImage$ = "" Or namedImage$ = otherNamedImage$
  ProcedureReturn #False
 EndIf
 otherInstance = GetInstanceOf(otherNamedImage$)
 If otherInstance = #Null
  ProcedureReturn #False
 EndIf
 otherInstance\output()
 If namedImage$ = "clipboard"
  SetClipboardImage(otherInstance\getImage())
  ProcedureReturn #True
 EndIf
 newInstance = newImageFilter(CopyImage(otherInstance\getImage(), #PB_Any))
 If newInstance = #Null
  ProcedureReturn #False
 EndIf
 *element = images\addKey(namedImage$)
 If *element = #Null
  ProcedureReturn #False
 EndIf
 If IsImage(*element\id)
  FreeImage(*element\id)
  *element\id = #Null
  *element\instance\delete()
  *element\instance = #Null
 EndIf
 *element\name = namedImage$
 *element\file = file$
 *element\id = newInstance\getImage()
 *element\instance = newInstance
 ProcedureReturn #True
EndProcedure


Procedure.i GetInstanceOf(namedImage$)
 Protected *element.IMAGE_STRUC
 namedImage$ = LCase(namedImage$)
 If namedImage$ = ""
  ProcedureReturn #Null
 EndIf
 *element = images\getKey(namedImage$)
 If *element
  ProcedureReturn *element\instance
 EndIf
 ProcedureReturn #Null
EndProcedure


Procedure.i UpdateInstanceOf(namedImage$)
 Protected *element.IMAGE_STRUC
 namedImage$ = LCase(namedImage$)
 If namedImage$ = ""
  ProcedureReturn #False
 EndIf
 *element = images\getKey(namedImage$)
 If *element
  If *element\instance
   *element\id = *element\instance\getImage()
   ProcedureReturn #True
  EndIf
 EndIf
 ProcedureReturn #False
EndProcedure


Procedure.i FreeInstanceOf(namedImage$)
 Protected *element.IMAGE_STRUC
 namedImage$ = LCase(namedImage$)
 If namedImage$ = ""
  ProcedureReturn #False
 EndIf
 If namedImage$ = "clipboard"
  ClearClipboard()
  ProcedureReturn #True
 EndIf
 *element = images\getKey(namedImage$)
 If *element
  FreeImage(*element\id)
  *element\instance\delete()
  If images\delKey(namedImage$)
   ProcedureReturn #True
  EndIf
 EndIf
EndProcedure


Procedure.i callCommand(command$, params$) ;functions mapping is done here
 Protected *instance.IImageFilter, *instance2.IImageFilter, *instance3.IImageFilter
 If LCase(command$) = "end"
  out_()
  PrintR("Done.")
  ExitProgram()
 ElseIf LCase(command$) = LCase("loadImage")
  *instance2 = GetInstanceOf(s_(params$, 2))
  If *instance2
   ProcedureReturn CopyInstanceOf(s_(params$, 1), s_(params$, 2))
  Else
   ProcedureReturn NewInstanceOf(s_(params$, 1), s_(params$, 2))
  EndIf
 Else
  *instance = GetInstanceOf(s_(params$, 1))
  If *instance = #Null
   ProcedureReturn #False
  EndIf
  ;-- execute commands - <
  Select LCase(command$)
   Case LCase("saveImage")
    *instance\output()
    Select LCase(GetExtensionPart(st_(params$, 2)))
     Case "bmp"
      If SaveImage(*instance\getImage(), st_(params$, 2), #PB_ImagePlugin_BMP) = #Null
       ProcedureReturn #False
      EndIf
     Case "jpg", "jpe", "jpeg"
      If SaveImage(*instance\getImage(), st_(params$, 2), #PB_ImagePlugin_JPEG, 8) = #Null
       ProcedureReturn #False
      EndIf
     Case "png"
      If SaveImage(*instance\getImage(), st_(params$, 2), #PB_ImagePlugin_PNG) = #Null
       ProcedureReturn #False
      EndIf
     Default
      ProcedureReturn #False
    EndSelect
   Case LCase("free") : ProcedureReturn FreeInstanceOf(s_(params$, 1))
   Case LCase("getWidth")
    out_("width = " + Str(*instance\getWidth()))
   Case LCase("getHeight")
    out_("height = " + Str(*instance\getHeight()))
   Case LCase("getResolution")
    out_("resolution = " + Str(*instance\getWidth()) + "x" + Str(*instance\getHeight()))
   Case LCase("getPixelCount")
    out_("pixels = " + Str(*instance\getPixelCount()))
   Case LCase("getAverage")
    out_("average = " + StrF(*instance\getAverage(i_(params$, 2))))
   Case LCase("getStandardDeviation")
    out_("standard deviation = " + StrF(*instance\getStandardDeviation(i_(params$, 2))))
   Case LCase("getCenterOfMassX")
    out_("center of mass x = " + StrF(*instance\getCenterOfMassX(i_(params$, 2))))
   Case LCase("getCenterOfMassY")
    out_("center of mass y = " + StrF(*instance\getCenterOfMassY(i_(params$, 2))))
   Case LCase("getCenterOfMass")
    out_("center of mass = " + StrF(*instance\getCenterOfMassX(i_(params$, 2))) + ", " + StrF(*instance\getCenterOfMassY(i_(params$, 2))))
   Case LCase("getSemimajorAxisAngle")
    out_("semi-major axis angle = " + StrF(*instance\getSemimajorAxisAngle(i_(params$, 2))))
   Case LCase("getExcentricity")
    out_("excentricity = " + StrF(*instance\getExcentricity(i_(params$, 2))))
   Case LCase("grayscale") : *instance\grayscale()
   Case LCase("invert") : *instance\invert()
   Case LCase("brightness") : *instance\brightness(i_(params$, 2))
   Case LCase("contrast") : *instance\contrast(f_(params$, 2))
   Case LCase("colorScale") : *instance\colorScale(f_(params$, 2), i_(params$, 3))
   Case LCase("gamma") : *instance\gamma(f_(params$, 2))
   Case LCase("normalize") : *instance\normalize()
   Case LCase("mirrorVertical") : *instance\mirrorVertical()
   Case LCase("mirrorHorizontal") : *instance\mirrorHorizontal()
   Case LCase("rotate")
    *instance\rotate(f_(params$, 2), i_(params$, 3), i_(params$, 4))
    ProcedureReturn UpdateInstanceOf(s_(params$, 1))
   Case LCase("resize")
    *instance\resize(i_(params$, 2), i_(params$, 3), i_(params$, 4))
    ProcedureReturn UpdateInstanceOf(s_(params$, 1))
   Case LCase("add")
    *instance2 = GetInstanceOf(s_(params$, 2))
    If *instance2 = #Null : ProcedureReturn #False : EndIf
    *instance\add_(*instance2, f_(params$, 3), i_(params$, 4))
   Case LCase("sub")
    *instance2 = GetInstanceOf(s_(params$, 2))
    If *instance2 = #Null : ProcedureReturn #False : EndIf
    *instance\sub_(*instance2, f_(params$, 3), i_(params$, 4))
   Case LCase("mul")
    *instance2 = GetInstanceOf(s_(params$, 2))
    If *instance2 = #Null : ProcedureReturn #False : EndIf
    *instance\mul_(*instance2, f_(params$, 3), i_(params$, 4))
   Case LCase("div")
    *instance2 = GetInstanceOf(s_(params$, 2))
    If *instance2 = #Null : ProcedureReturn #False : EndIf
    *instance\div_(*instance2, f_(params$, 3), i_(params$, 4))
   Case LCase("xor")
    *instance2 = GetInstanceOf(s_(params$, 2))
    If *instance2 = #Null : ProcedureReturn #False : EndIf
    *instance\xor_(*instance2)
   Case LCase("and")
    *instance2 = GetInstanceOf(s_(params$, 2))
    If *instance2 = #Null : ProcedureReturn #False : EndIf
    *instance\and_(*instance2)
   Case LCase("or")
    *instance2 = GetInstanceOf(s_(params$, 2))
    If *instance2 = #Null : ProcedureReturn #False : EndIf
    *instance\or_(*instance2)
   Case LCase("weight")
    *instance2 = GetInstanceOf(s_(params$, 2))
    If *instance2 = #Null : ProcedureReturn #False : EndIf
    *instance\weight(*instance2, f_(params$, 3), i_(params$, 4))
   Case LCase("weightMask")
    *instance2 = GetInstanceOf(s_(params$, 2))
    If *instance2 = #Null : ProcedureReturn #False : EndIf
    *instance3 = GetInstanceOf(s_(params$, 3))
    If *instance3 = #Null : ProcedureReturn #False : EndIf
    *instance\weightMask(*instance2, *instance3, f_(params$, 4), i_(params$, 5))
   Case LCase("difference")
    *instance2 = GetInstanceOf(s_(params$, 2))
    If *instance2 = #Null : ProcedureReturn #False : EndIf
    *instance\difference(*instance2, f_(params$, 3), i_(params$, 4))
   Case LCase("euclidianNorm")
    *instance2 = GetInstanceOf(s_(params$, 2))
    If *instance2 = #Null : ProcedureReturn #False : EndIf
    *instance\euclidianNorm(*instance2, i_(params$, 3))
   Case LCase("manhattenNorm")
    *instance2 = GetInstanceOf(s_(params$, 2))
    If *instance2 = #Null : ProcedureReturn #False : EndIf
    *instance\manhattenNorm(*instance2, i_(params$, 3))
   Case LCase("addColorOverlay") : *instance\addColorOverlay(i_(params$, 2), f_(params$, 3))
   Case LCase("removeColorOverlay") : *instance\removeColorOverlay(i_(params$, 2), f_(params$, 3))
   Case LCase("median") : *instance\median(i_(params$, 2))
   Case LCase("nearMedian") : *instance\nearMedian(i_(params$, 2), i_(params$, 3))
   Case LCase("binomial") : *instance\binomial(i_(params$, 2))
   Case LCase("minMax") : *instance\minMax(i_(params$, 2))
   Case LCase("DoG") : *instance\DoG(i_(params$, 2), i_(params$, 3))
   Case LCase("houghTransformation")
    *instance\houghTransformation(i_(params$, 2))
    ProcedureReturn UpdateInstanceOf(s_(params$, 1))
   Case LCase("threshold") : *instance\threshold(i_(params$, 2), i_(params$, 3))
   Case LCase("regionGrowing") : *instance\regionGrowing(i_(params$, 2), i_(params$, 3), i_(params$, 4))
   Case LCase("dilate") : *instance\dilate(i_(params$, 2), st_(params$, 3), i_(params$, 4))
   Case LCase("erode") : *instance\erode(i_(params$, 2), st_(params$, 3), i_(params$, 4))
   Case LCase("closing") : *instance\closing(i_(params$, 2), st_(params$, 3), i_(params$, 4))
   Case LCase("opening") : *instance\opening(i_(params$, 2), st_(params$, 3), i_(params$, 4))
   Case LCase("thin") : *instance\thin(i_(params$, 2), i_(params$, 3))
   Case LCase("skeletonization") : *instance\skeletonization(i_(params$, 2))
   Case LCase("generic") : *instance\generic(st_(params$, 2))
   Case LCase("bswap") : *instance\bswap()
   Default
    ProcedureReturn #False
  EndSelect
 EndIf
 ProcedureReturn #True
EndProcedure


Procedure ExitProgram()
;  Input()
 End
EndProcedure



;----------main--------- <
OpenConsole()

file$ = ProgramParameter(0)

stdin.i = #False
Select LCase(ProgramParameter(0))
 Case "-i", "/i"
  stdin = #True
 Case "-v", "/v", "-version", "--version"
  PrintN("FilterInterpreter " + #P_Version + " - coded by pcfreak")
  ExitProgram()
 Default
  If FileSize(file$) <= 0
   PrintN("FilterInterpreter " + #P_Version + " - coded by pcfreak")
   PrintN("Syntax: [option] [file]")
   PrintN("")
   PrintN("   file    the script file which shell be interpreted")
   PrintN("")
   PrintN("Options:")
   PrintN("   -i      use standard input instead of a file")
   PrintN("   -v      displays the version of the program")
   PrintN("")
   PrintN("no or wrong input will show this help")
   ExitProgram()
  EndIf
EndSelect

If FileSize(file$) > 0 Or stdin
 out_("Reading script file...")
 If stdin
  Index.i = 1
  Repeat
   Line$ = Trim(Input())
   If Line$ <> #PB_Input_Eof
    CompilerIf #PB_Compiler_Unicode
     If Index = 1 And Asc(Left(Line$, 1)) = $FEFF
      Line$ = Right(Line$, Len(Line$) - 1)
     EndIf
    CompilerEndIf
    PrintR("parsing line...", Line$)
    If parseLine(Line$, Index) = #False
     PrintR("error in line " + Str(Index))
     ExitProgram()
    EndIf
    Index + 1
   EndIf
  Until Line$ = #PB_Input_Eof
  If Index = 1
   ExitProgram()
  EndIf
 Else
  FileID.i = ReadFile(#PB_Any, file$)
  If FileID
    BOM = ReadStringFormat(FileID)
    Index.i = 1
    While Eof(FileID) = #False
     Line$ = Trim(ReadString(FileID, BOM))
     PrintR("parsing line...", Line$)
     If parseLine(Line$, Index) = #False
      PrintR("error in line " + Str(Index))
      ExitProgram()
     EndIf
     Index + 1
    Wend
   CloseFile(FileID)
  Else
   out_("Couldn't open file.")
   ExitProgram()
  EndIf
 EndIf
 If GarbageCollectorInit() = #False
  PrintR("internal memory management error")
  ExitProgram()
 EndIf
 out_()
 PrintR("", "Executing commands...")
 ForEach prog()
  PrintR("processing command...", prog()\method + "(" + ReplaceString(prog()\params, Chr(1), ", ") + ")")
  If callCommand(prog()\method, prog()\params) = #False
   PrintR("error in line " + Str(prog()\line))
   ExitProgram()
  EndIf
  GarbageCollectorTest(prog()\line)
 Next
 out_()
 PrintR("Done.")
 ExitProgram()
EndIf


Well it's more like a batch processor.
Here is also some quick guide about the batch processor I just found :p
Code:
Use:
----

FilterInterpreter.exe scriptFile


Input formats:
--------------

 - bmp
 - jp2, jpx
 - jpg, jpe, jpeg
 - png
 - tga
 - tif, tiff


Output formats:
---------------

 - bmp
 - jpg, jpe, jpeg
 - png


Scripting:
----------

Note:
 - each command stands in _one_ line
 - no calculation possible, like 1 + 2
 - every parameter of a function needs to be specified
 - the type of the parameter is given as in the definitions below
 - the default value of each parameter can be used as given in the definitions below
 - image stands for the loaded image and needs to be specified for each command
 - parameters are separated by comma
 - strings can be used by surrounding the expressing with " or '
 - colors can be defined in hex with $AABBGGRR (A = Alpha, B = Blue, G = Green, R = Red)
   example for light gray: $00C0C0C0

Integers:
   1658
   0
   -56156
   %1011010110
   $A3D10C5B

Floats:
   123.518
   1.00
   -32.15

Strings:
   "Hello World!"
   'Testing...'

Comment:
   ; in front of each line which shall be a comment


Load file:
   image = C:\file.jpg

Load image from clipboard:
   image = clipboard

Copy image:
   newImage = image

Copy image to clipbaord:
   clipboard = image

Save image:
   saveImage(image, "C:\file.jpg")

Free image:
   free(image)

Free clipboard:
   free(clipboard)

End execution:
   end


Commands:
 information:
   Integer: getWidth(image)
   Integer: getHeight(image)
   String: getResolution(image)
   Integer: getPixelCount(image)
   Float: getAverage(image, Integer: channel = -1)
   Float: getStandardDeviation(image, Integer: channel = -1)
   Float: getCenterOfMassX(image, Integer: channel = -1)
   Float: getCenterOfMassY(image, Integer: channel = -1)
   String: getCenterOfMass(image, Integer: channel = -1)
   Float: getSemimajorAxisAngle(image, Integer: channel = -1)
   Float: getExcentricity(image, Integer: channel = -1)
 color:
   grayscale(image)
   invert(image)
   brightness(image, Integer: delta)
   contrast(image, Float: factor)
   colorScale(image, Float: factor = 1, Integer: delta = 0)
   multiColorScale(image, Float: factor = 1, Integer: deltaColor = 0)
   gamma(image, Float: value)
   normalize(image)
 transform:
   mirrorVertical(image)
   mirrorHorizontal(image)
   rotate(image, Float: angle, Integer: nonBilinear = 0, Integer: resize = 0)
   resize(image, Integer: width, Integer: height, Integer: mode)
     mode:
       0 - nearest neighbor
 overlay:
   add(image, srcImage, Float: factor = 1, Integer: delta = 0)
   sub(image, srcImage, Float: factor = 1, Integer: delta = 0)
   mul(image, srcImage, Float: factor = 1, Integer: delta = 0)
   div(image, srcImage, Float: factor = 1, Integer: delta = 0)
   xor(image, srcImage)
   and(image, srcImage)
   or(image, srcImage)
   weight(image, srcImage, Float: factor = 1, Integer: delta = 0)
   weightMask(image, otherImage, maskImage, Float: factor = 1, Integer: delta = 0)
   difference(image, srcImage, Float: factor = 1, Integer: delta = 0)
   euclidianNorm(image, srcImage, Integer: offset)
   manhattenNorm(image, srcImage, Integer: offset)
   addColorOverlay(image, Integer: color, Float: opacity)
   removeColorOverlay(image, Integer: color, Float: opacity)
 denoise:
   median(image, Integer: size)
   nearMedian(image, Integer: normalSize, Integer: nearSize)
   binomial(image, Integer: size)
 edge detection:
   minMax(image, Integer: size)
   DoG(image, Integer: q, Integer: p)
   houghTransformation(image, Integer: threshold)
 segmenting (grayscale):
   threshold(image, Integer: value, Integer: keepColor = 0)
   regionGrowing(image, Integer: x, Integer: y, Integer: maxDelta)
 morphology (segmented):
   dilate(image, Integer: label, String: mask, Integer: times)
   erode(image, Integer: label, String: mask, Integer: times)
   closing(image, Integer: label, String: mask, Integer: times)
   opening(image, Integer: label, String: mask, Integer: times)
   thin(image, Integer: label, Integer: times)
   skeletonization(image, Integer: label)
 others:
   generic(image, String: filter)
   bswap()


Parameter definitions:
 mask:
   |   separates rows
   ,   separates columns
   first columns, then rows
   example: "0,1,0|1,1,1|0,1,0"
 filter:
   |   separates rows
   ,   separates columns
   ;   separates parameters
   first columns, then rows
   first filter matrix, then divisor, then offset
   example: "1,2,1|2,4,2|1,2,1;16;0"


Top
 Profile  
 
 Post subject: Re: class for image manipulation (OOP)
PostPosted: Sun Apr 15, 2012 12:55 pm 
Offline
Enthusiast
Enthusiast
User avatar

Joined: Sun Oct 31, 2004 10:54 am
Posts: 511
Thanks :)

_________________
Image
************************************
site : http://michel.dobro.free.fr/
Videos : http://www.youtube.com/user/DobroMG
************************************


Top
 Profile  
 
Display posts from previous:  Sort by  
Post new topic Reply to topic  [ 6 posts ] 

All times are UTC + 1 hour


Who is online

Users browsing this forum: No registered users and 7 guests


You cannot post new topics in this forum
You cannot reply to topics in this forum
You cannot edit your posts in this forum
You cannot delete your posts in this forum

Search for:
Jump to:  

 


Powered by phpBB © 2008 phpBB Group
subSilver+ theme by Canver Software, sponsor Sanal Modifiye