Image Filters

Share your advanced PureBasic knowledge/code with the community.
wilbert
PureBasic Expert
PureBasic Expert
Posts: 3942
Joined: Sun Aug 08, 2004 5:21 am
Location: Netherlands

Image Filters

Post by wilbert »

Image Filter routine (requires a processor capable of SSE2)

ImageFiter.pbi

Code: Select all

Structure IFRGBA
  r.f
  g.f
  b.f
  a.f
EndStructure

Structure IFContext
  x.l     ; x
  y.l     ; y
  w.l     ; width
  h.l     ; height
  ri.f    ; red   in [0.0f - 1.0f]
  gi.f    ; green in [0.0f - 1.0f]
  bi.f    ; blue  in [0.0f - 1.0f]
  ai.f    ; alpha in [0.0f - 1.0f]
  ro.f    ; red   out [0.0f - 1.0f]
  go.f    ; green out [0.0f - 1.0f]
  bo.f    ; blue  out [0.0f - 1.0f]
  ao.f    ; alpha out [0.0f - 1.0f]
  arg1.q  ; argument 1
  arg2.q  ; argument 2
  px.IFRGBA[0] ; pixel buffer  
EndStructure

Prototype ProtoIFCallBack(*ctx.IFContext)

Procedure.i ImageFilter(Image.i, *ImageFilterCallback, arg1.q = 0, arg2.q = 0)
  
  If IsImage(Image) = 0
    ProcedureReturn 0
  EndIf
  
  Protected result.i, i.i, x.l, y.l, c.l
  Protected width.l = ImageWidth(Image)
  Protected height.l = ImageHeight(Image)
  Protected *mem_unaligned = AllocateMemory(width * height * 16 + 80)
  Protected *mem.IFContext = (*mem_unaligned + 15) & -16
  Protected Callback.ProtoIFCallback = *ImageFilterCallback
  
  If *mem_unaligned
    result.i = CreateImage(#PB_Any, width, height, 32)
    If result
      *mem\w = width
      *mem\h = height
      *mem\arg1 = arg1
      *mem\arg2 = arg2
      StartDrawing(ImageOutput(Image))
      DrawingMode(#PB_2DDrawing_AllChannels)
      
      i = *mem + 64
      y = 0
      While y < height
        x = 0
        While x < width
          c = Point(x, y)
          !mov eax, 0x3b808081; 1.0f / 255.0f 
          !movd xmm2, eax
          !pshufd xmm2, xmm2, 0
          !pxor xmm1, xmm1
          !movd xmm0, [p.v_c]
          !punpcklbw xmm0, xmm1
          !punpcklwd xmm0, xmm1
          !cvtdq2ps xmm0, xmm0
          !mulps xmm0, xmm2
          CompilerIf #PB_Compiler_Processor = #PB_Processor_x86
            !mov edx, [p.v_i]
            !movdqa [edx], xmm0
            !add edx, 16
            !mov [p.v_i], edx
          CompilerElse
            !mov rdx, [p.v_i]
            !movdqa [rdx], xmm0
            !add rdx, 16
            !mov [p.v_i], rdx
          CompilerEndIf
          x + 1
        Wend
        y + 1
      Wend
      
      StopDrawing()
      StartDrawing(ImageOutput(result))
      DrawingMode(#PB_2DDrawing_AllChannels)
      
      i = *mem + 64
      y = 0
      While y < height
        x = 0
        While x < width
          CompilerIf #PB_Compiler_Processor = #PB_Processor_x86
            !mov edx, [p.v_i]
            !movdqa xmm0, [edx]
            !add edx, 16
            !mov [p.v_i], edx
            !mov edx, [p.p_mem]
            !movdqa [edx + 16], xmm0
            !movdqa [edx + 32], xmm0
            !mov eax, [p.v_x]
            !mov [edx], eax
            !mov eax, [p.v_y]
            !mov [edx + 4], eax
            Callback(*mem)
            !mov edx, [p.p_mem]
            !movdqa xmm0, [edx + 32]
          CompilerElse
            !mov rdx, [p.v_i]
            !movdqa xmm0, [rdx]
            !add rdx, 16
            !mov [p.v_i], rdx
            !mov rdx, [p.p_mem]
            !movdqa [rdx + 16], xmm0
            !movdqa [rdx + 32], xmm0
            !mov eax, [p.v_x]
            !mov dword [rdx], eax
            !mov eax, [p.v_y]
            !mov dword [rdx + 4], eax
            Callback(*mem)
            !mov rdx, [p.p_mem]
            !movdqa xmm0, [rdx + 32]
          CompilerEndIf
          !mov eax, 0x437f0000; 255.0f
          !movd xmm2, eax
          !pshufd xmm2, xmm2, 0
          !mulps xmm0, xmm2
          !cvtps2dq xmm0, xmm0
          !packssdw xmm0, xmm0
          !packuswb xmm0, xmm0
          !movd [p.v_c], xmm0
          Plot(x, y, c)
          x + 1
        Wend
        y + 1
      Wend
      
      StopDrawing()
    EndIf
    FreeMemory(*mem_unaligned)
  EndIf
  ProcedureReturn result
  
EndProcedure
Last edited by wilbert on Mon Jun 11, 2012 10:16 am, edited 2 times in total.
wilbert
PureBasic Expert
PureBasic Expert
Posts: 3942
Joined: Sun Aug 08, 2004 5:21 am
Location: Netherlands

Re: Image Filters

Post by wilbert »

Example

Code: Select all

EnableExplicit

XIncludeFile "ImageFilter.pbi"
UsePNGImageDecoder()

Procedure Scanlines(*ctx.IFContext)
  If *ctx\y % 2
    *ctx\ro = *ctx\ri - 0.15
    *ctx\go = *ctx\gi - 0.15
    *ctx\bo = *ctx\bi - 0.15
  EndIf
EndProcedure

Procedure ColorReverse(*ctx.IFContext)
  *ctx\ro = 1.0 - *ctx\ri
  *ctx\go = 1.0 - *ctx\gi
  *ctx\bo = 1.0 - *ctx\bi
EndProcedure

Procedure Grayscale(*ctx.IFContext)
  *ctx\ro = 0.266 * *ctx\ri + 0.587 * *ctx\gi + 0.114 * *ctx\bi
  *ctx\go = *ctx\ro
  *ctx\bo = *ctx\ro
EndProcedure

Procedure FlipVertical(*ctx.IFContext)
  Static offset
  offset = *ctx\w * (*ctx\h - *ctx\y - 1) + *ctx\x
  *ctx\ro = *ctx\px[offset]\r
  *ctx\go = *ctx\px[offset]\g
  *ctx\bo = *ctx\px[offset]\b
  *ctx\ao = *ctx\px[offset]\a
EndProcedure

Define Original = CatchImage(#PB_Any, ?png_start)
Define Filtered1 = ImageFilter(Original, @Scanlines())
Define Filtered2 = ImageFilter(Original, @Grayscale())
Define Filtered3 = ImageFilter(Original, @FlipVertical())

If OpenWindow(0, 0, 0, 245, 105, "ImageFilter", #PB_Window_SystemMenu | #PB_Window_ScreenCentered)
  ImageGadget(0, 10, 10, 24, 24, ImageID(Original), #PB_Image_Border)
  ImageGadget(1, 50, 10, 24, 24, ImageID(Filtered1), #PB_Image_Border)
  ImageGadget(2, 90, 10, 24, 24, ImageID(Filtered2), #PB_Image_Border)
  ImageGadget(3, 130, 10, 24, 24, ImageID(Filtered3), #PB_Image_Border)
  Repeat : Until WaitWindowEvent() = #PB_Event_CloseWindow
EndIf

DataSection
  png_start:
  Data.q $0A1A0A0D474E5089,$524448490D000000,$1800000018000000,$3D77E00000000608,$58457419000000F8
  Data.q $72617774666F5374,$2065626F64410065,$6165526567616D49,$00003C65C9717964,$DA78544144492C03
  Data.q $FE1451144BDF569C,$A4574CC55DD75A66,$2BA41FA212D02568,$F427F42BA22F464B,$883D151043D09FD0
  Data.q $44BD8FB0FAD29994,$AAE5150410443D14,$4242148116D45224,$D75B48DC08ADB63F,$DB333B9CEDCD7F6D
  Data.q $F6770E075BAACECC,$1EE7B9CCEFBEF9CE,$FE85045E26954156,$8B1FB98A63872800,$471E3C47EFDF84C5
  Data.q $255108C362AF6F6F,$C70BE42788406CF9,$B9B9C891ED9E7C84,$2E51199999B56139,$134810193E4A6EA0
  Data.q $2335F4172C07D6AE,$8B6ADADAD101A220,$E20286FC0E7CF9F5,$026AE022AFC0B75E,$0DBDC4599F9C8856
  Data.q $2F8B6E3C5CE86B48,$945D3B880BD58B16,$7C06B7FC896A0139,$969F1572D3EA025B,$2A5DDBBFDA35FDF4
  Data.q $871B8809D569A687,$85F039649A6BCCF4,$AB945CCD117A7708,$956066DAF22982C2,$4043A81EEB5D5BD6
  Data.q $85B7722290283D5C,$428508232B91077C,$4430939F72DFE572,$156DEC0515DD6BD4,$B2CDADD220502FD9
  Data.q $D930EABB024C911D,$18A3468B4DC92A32,$0B4B406BE2079E4C,$28B600FF2E794325,$F7F45DAC51BE4E50
  Data.q $DE42D1BC9D3EF8C7,$06060618DB64C5E6,$7130614D4D4D991C,$44431A917464480E,$18809B156F339125
  Data.q $B9061C9D04274BDA,$44DB922BC73BC89F,$8917110CB952CF16,$0B0B8DC3191A4CFC,$43D40FD4EA9C5579
  Data.q $3EB6A95FEA52CF35,$BF7F7F4319EF1E0F,$F1C71CF7E73D62CC,$AD30CF8ECE369712,$0E9948B8F643F4E5
  Data.q $0747E0A456F4272D,$6114BC708AB72736,$8161AFF51B78F33C,$1A9B43C12F56EFDB,$AB46BA0F17B378F5
  Data.q $F12CBEEC3C8AB726,$BAFE52F9E2CD4792,$48A122DCE4EDCA59,$B366C88C99322224,$DE45C9BC638CECFF
  Data.q $C11C377C1F54E2CE,$F5D30E38A28A1060,$A80F31A5FA6A0471,$88E43DD8507BEA1F,$68B8EB0DB1773C63
  Data.q $257EA9F9FAA46E15,$A20CF932134695F9,$9E0136B095703843,$3D6CCE4AFCAF1525,$F980B95C796B9266
  Data.q $02542988B10796AC,$E3CD34F02C69E4AD,$BDED82D5AE5D1D7E,$7A3C00322CF9B315,$BEBEE2274B13204D
  Data.q $B7199DE942F3EA3E,$1D40A54A944AD99E,$DECE0F3F6DDBB701,$96AD395291F0FAB0,$9E982FC37E24E5CB
  Data.q $CDB064244899BE9E,$F18E339197876328,$2E361E1C38417E1B,$D1FED286868689CE,$DB79F9F9B32382B5
  Data.q $6970C4C4C4F93397,$DAC5A9A6DBBB534C,$D7FB0D2AF6CA3BC9,$D83E57578BDFBF65,$E2D7FD54A1A70276
  Data.q $15480003008FED3F,$0000E3C04A8E9369,$42AE444E45490000
  Data.b $60,$82
  png_end:
EndDataSection
User avatar
djes
Addict
Addict
Posts: 1806
Joined: Sat Feb 19, 2005 2:46 pm
Location: Pas-de-Calais, France

Re: Image Filters

Post by djes »

Wow, very nice ! Thank you :)
Post Reply