
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: Select all
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