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
  
EndProcedureCode: 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
