Median blur effect (gaussian-like)

Share your advanced PureBasic knowledge/code with the community.
User avatar
Keya
Addict
Addict
Posts: 1891
Joined: Thu Jun 04, 2015 7:10 am

Median blur effect (gaussian-like)

Post by Keya »

I was looking for blur functions and the only two I could find was this one which is a box blur but it had problems with some pictures i tried, and wilbert has an absolutely amazing MMX-based proper Gaussian blur here, but i couldnt find any others for PB!

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 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).
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?)
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
Image

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
Last edited by Keya on Mon Jan 18, 2016 8:59 am, edited 3 times in total.
User avatar
RSBasic
Moderator
Moderator
Posts: 1218
Joined: Thu Dec 31, 2009 11:05 pm
Location: Gernsbach (Germany)
Contact:

Re: Median blur effect (gaussian-like)

Post by RSBasic »

Very nice. :)
Image
Image
User avatar
Lunasole
Addict
Addict
Posts: 1091
Joined: Mon Oct 26, 2015 2:55 am
Location: UA
Contact:

Re: Median blur effect (gaussian-like)

Post by Lunasole »

Nice short sample 8)
"W̷i̷s̷h̷i̷n̷g o̷n a s̷t̷a̷r"
User avatar
Kwai chang caine
Always Here
Always Here
Posts: 5342
Joined: Sun Nov 05, 2006 11:42 pm
Location: Lyon - France

Re: Median blur effect (gaussian-like)

Post by Kwai chang caine »

Cool works great on W7 :D
Thanks for sharing 8)
ImageThe happiness is a road...
Not a destination
BarryG
Addict
Addict
Posts: 3292
Joined: Thu Apr 18, 2019 8:17 am

Re: Median blur effect (gaussian-like)

Post by BarryG »

Thanks Keya! Very useful for an idea I had today for my app.
Post Reply