
Gaussian.pbi
Code: Select all
; Gaussian.pbi (requires MMX)
Procedure Gaussian1D(*PixelBuf32, NumPixels, NextPixelOffset = 4)
; Matrix : 1 - 4 - 6 - 4 - 1 (/16)
; exit if NumPixels < 3
!mov ecx, [p.v_NumPixels]
!sub ecx, 3
!js gaussian1d_exit
!mov eax, [p.v_NextPixelOffset]
; initial setup
CompilerIf #PB_Compiler_Processor = #PB_Processor_x64
!mov rdx, [p.p_PixelBuf32]
!movd mm1, [rdx]
!movd mm4, [rdx + rax]
CompilerElse
!mov edx, [p.p_PixelBuf32]
!movd mm1, [edx]
!movd mm4, [edx + eax]
CompilerEndIf
!pxor mm7, mm7
!pxor mm6, mm6
!punpcklbw mm1, mm6
!punpcklbw mm4, mm6
!movq mm2, mm1
!movq mm3, mm1
; loop
!gaussian1d_loop0:
CompilerIf #PB_Compiler_Processor = #PB_Processor_x64
!movd mm5, [rdx + rax * 2]
CompilerElse
!movd mm5, [edx + eax * 2]
CompilerEndIf
!punpcklbw mm5, mm6
!gaussian1d_loop1:
!movq mm0, mm2
!paddw mm0, mm3
!paddw mm0, mm4
!psllw mm0, 2
!paddw mm0, mm1
!paddw mm0, mm3
!paddw mm0, mm3
!paddw mm0, mm5
!paddw mm0, mm7
!movq mm7, mm0
!psraw mm0, 4
!packuswb mm0, mm0
CompilerIf #PB_Compiler_Processor = #PB_Processor_x64
!movd [rdx], mm0
!add rdx, rax
CompilerElse
!movd [edx], mm0
!add edx, eax
CompilerEndIf
!movq mm1, mm2
!movq mm2, mm3
!movq mm3, mm4
!movq mm4, mm5
!punpcklbw mm0, mm6
!psllw mm0, 4
!psubw mm7, mm0
!dec ecx
!jns gaussian1d_loop0
!cmp ecx, -3
!jne gaussian1d_loop1
!gaussian1d_exit:
!emms
EndProcedure
Procedure Gaussian2D(*PixelBuf32, Width, Height, BufferPitch = 0)
; 1 - 4 - 6 - 4 - 1
; 4 - 16 - 24 - 16 - 4
; 6 - 24 - 36 - 24 - 4
; 4 - 16 - 24 - 16 - 4
; 1 - 4 - 6 - 4 - 1
If BufferPitch = 0
BufferPitch = Width << 2
EndIf
Protected i.i = 0
While i < Height
Gaussian1D(*PixelBuf32 + BufferPitch * i, Width)
i + 1
Wend
i = 0
While i < Width
Gaussian1D(*PixelBuf32 + i << 2, Height, BufferPitch)
i + 1
Wend
EndProcedure
Procedure GaussianBlur(Image, Strength = 1)
Protected.i i, w, h, x, y, max_x, max_y
If StartDrawing(ImageOutput(Image))
w = OutputWidth()
h = OutputHeight()
If DrawingBufferPixelFormat() & $60; 32 bit buffer ?
For i = 0 To Strength
Gaussian2D(DrawingBuffer(), w, h, DrawingBufferPitch())
Next
Else
max_x = w - 1
max_y = h - 1
Dim Buffer.l(max_y, max_x)
DrawingMode(#PB_2DDrawing_AllChannels)
For y = 0 To max_y
For x = 0 To max_x
Buffer(y, x) = Point(x, y)
Next
Next
For i = 0 To Strength
Gaussian2D(@Buffer(), w, h)
Next
For y = 0 To max_y
For x = 0 To max_x
Plot(x, y, Buffer(y, x))
Next
Next
EndIf
StopDrawing()
EndIf
EndProcedure
Code: Select all
EnableExplicit
XIncludeFile "Gaussian.pbi"
UseJPEGImageDecoder()
UsePNGImageDecoder()
Define.i w, h
LoadImage(0, "MyImage.jpg")
w = ImageWidth(0)
h = ImageHeight(0)
GaussianBlur(0)
If OpenWindow(0, 0, 0, w, h, "GaussianBlur Filter", #PB_Window_SystemMenu | #PB_Window_ScreenCentered)
ImageGadget(0, 0, 0, w, h, ImageID(0))
Repeat : Until WaitWindowEvent() = #PB_Event_CloseWindow
EndIf