Anyway I came across this http://www.codeproject.com/Articles/616 ... a-Blurring (original author Matthew Hazlett, 22 Feb 2004) and it looked tantalizingly simple, just begging me to try porting it so I had a go and it was painless enough heehee. In feedback to the code somebody clarified that it's a median filter. The author describes it as
The quality of the blur seems quite good, it supports full RGBA, and it has variable width+height kernel matrix (but unweighted unlike true gaussian) so you can also do vertical and horizontal blurs (motion blurs?)The reason it isn't exactly the same as the real mccoy (gaussian) is it doesn't take into account a transform matrix, so as a result the colors all have the same weighted values (but you can't really tell a difference).
Here is 1) original, 2) blur x2 (smallest), 3) blur x8 - it doesnt seem to have a ceiling so you can go far beyond 8, 4) horizontal blur x8, 5) vertical blur x8
It's a direct port of the VB demo however, and I can see you all cringing now as you anticipate that yes - this uses Plot() & Point() to work one pixel at a time as per the original so it's quite slow, OUCH! so there's a lot of room for optimization but its nice and easy to learn from in this slow-but-small state!
Code: Select all
;Based on http://www.codeproject.com/Articles/6162/Gaussian-And-Alpha-Blurring (by Matthew Hazlett, 22 Feb 2004)
EnableExplicit
Structure _SIZE
Height.i
Width.i
EndStructure
Structure _SIZEF
Height.f
Width.f
EndStructure
Structure Color
R.a
G.a
B.a
A.a
EndStructure
Procedure.l Average(*Size._SIZE, *imageSize._SIZEF, PixelX, PixelY)
Dim pixel(Int(*imageSize\Height * *imageSize\Width))
Protected pixels, x, y
;' Find the color for each pixel and add it to a new array.
;' Remember a 5X5 area on or near the edge will ask for pixels that don't exist in our image, this will filter those out.
For x = PixelX - (*Size\Width / 2) To PixelX + (*Size\Width / 2)
For y = Pixely - (*Size\Height / 2) To Pixely + (*Size\Height / 2)
If (x > 0 And x < *imageSize\Width) And (y > 0 And y < *imageSize\Height)
pixel(pixels) = Point(x, y)
pixels+1
EndIf
Next
Next
;' Average the A, R, G, B channels reflected in the array
Protected thisColor, alpha, red, green, blue
For thisColor = 0 To pixels-1
alpha + Alpha(pixel(thisColor))
red + Red(pixel(thisColor))
green + Green(pixel(thisColor))
blue + Blue(pixel(thisColor))
Next
If pixels = 0: ProcedureReturn 0: EndIf
ProcedureReturn RGBA(red/pixels, green/pixels, blue/pixels, alpha/pixels) ;' Return the sum of the colors / number of colors (the avg)
EndProcedure
Procedure MedianBlur(hImg, *ImgSize._SIZEF, alphaEdgesOnly.i, *blurSize._SIZE)
Protected PixelX, PixelY
StartDrawing(ImageOutput(hImg))
For PixelY = 0 To *ImgSize\Height - 1
For PixelX = 0 To *ImgSize\Width - 1
If Not alphaEdgesOnly ;' Blur everything
Plot(PixelX, PixelY, Average(*blurSize, *ImgSize, PixelX, PixelY))
ElseIf Alpha(Point(PixelX, PixelY)) <> 255 ;' Alpha blur channel check
Plot(PixelX, PixelY, Average(*blurSize, *ImgSize, PixelX, PixelY))
EndIf
Next
Next
StopDrawing()
EndProcedure
;-- TEST ----------------------------------------------------------------------------------------------------
Define blursize._SIZE, hImg = LoadImage(#PB_Any, #PB_Compiler_Home+"/Examples/Sources/data/purebasic.bmp") ;500, 500,32, #PB_Image_Transparent)
If hImg = 0: MessageRequester("Error","Load file fail"): End: EndIf
Define ImgSize._SIZEF\Height = ImageHeight(hImg): ImgSize._SIZEF\Width = ImageWidth(hImg)
OpenWindow(0, 0, 0, ImgSize._SIZEF\Width, ImgSize._SIZEF\Height*5, "Blur", #PB_Window_SystemMenu | #PB_Window_SizeGadget | #PB_Window_ScreenCentered)
Define hBlurImg1 = CopyImage(hImg, #PB_Any)
blursize._SIZE\Height = 2: blursize._SIZE\Width = 2 ;x2 blur (smallest)
MedianBlur(hBlurImg1, @ImgSize, #False, blursize)
Define hBlurImg2 = CopyImage(hImg, #PB_Any)
blursize._SIZE\Height = 8: blursize._SIZE\Width = 8 ;x8 blur
MedianBlur(hBlurImg2, @ImgSize, #False, blursize)
Define hBlurImg3 = CopyImage(hImg, #PB_Any)
blursize._SIZE\Height = 2: blursize._SIZE\Width = 8 ;x8 Horizontal blur
MedianBlur(hBlurImg3, @ImgSize, #False, blursize)
Define hBlurImg4 = CopyImage(hImg, #PB_Any)
blursize._SIZE\Height = 8: blursize._SIZE\Width = 2 ;x8 Vertical blur
MedianBlur(hBlurImg4, @ImgSize, #False, blursize)
ImageGadget(0, 0, 0, ImgSize._SIZEF\Width, ImgSize._SIZEF\Height, ImageID(hImg))
ImageGadget(1, 0, ImgSize\Height, ImgSize._SIZEF\Width, ImgSize._SIZEF\Height, ImageID(hBlurImg1))
ImageGadget(2, 0, ImgSize\Height*2, ImgSize._SIZEF\Width, ImgSize._SIZEF\Height, ImageID(hBlurImg2))
ImageGadget(3, 0, ImgSize\Height*3, ImgSize._SIZEF\Width, ImgSize._SIZEF\Height, ImageID(hBlurImg3))
ImageGadget(4, 0, ImgSize\Height*4, ImgSize._SIZEF\Width, ImgSize._SIZEF\Height, ImageID(hBlurImg4))
Repeat
Define Event = WaitWindowEvent()
If Event = #PB_Event_CloseWindow: End: EndIf
ForEver