voici un filtre de convolution de noyau 3x3
il est multi-thread et utilise des nombres flottants
les pixels du bord de l'image ne sont pas traités
Code : Tout sélectionner
;-------------------------------------------------------------------
Global Dim Filter_convolution3x3_tab.f(11)
Global Dim param.i(6)
;-------------------------------------------------------------------
Macro clampRGB(r,g,b)
If r<0:r=0:EndIf
If g<0:g=0:EndIf
If b<0:b=0:EndIf
If r>255:r=255:EndIf
If g>255:g=255:EndIf
If b>255:b=255:EndIf
EndMacro
Macro returnRGB(p,var)
pixel=PeekL(source_p + p)
ri = (pixel & $ff0000)>>16
gi = (pixel & $ff00)>>8
bi = (pixel & $ff)
r#var=(ri)
g#var=(gi)
b#var=(bi)
EndMacro
Procedure Filter_convolution3x3_set(v1,v2.f)
If v1<0 Or v1>10 : ProcedureReturn : EndIf
Filter_convolution3x3_tab(v1) = v2
EndProcedure
; programme principal
Procedure Filter_convolution3x3_thread(i)
Protected x.l , y.l , pixel.l
Protected r.f , r1.f , r2.f , r3.f , r4.f , r5.f , r6.f , r7.f , r8.f , r9.f
Protected g.f , g1.f , g2.f , g3.f , g4.f , g5.f , g6.f , g7.f , g8.f , g9.f
Protected b.f , b1.f , b2.f , b3.f , b4.f , b5.f , b6.f , b7.f , b8.f , b9.f
Protected dif.f
Protected ri.l , gi.l , bi.l
Protected start.l,stop.l
Protected source_p.i , cible_p.i , lg.l , ht.l , lg4.l
source_p = param(0)
cible_p = param(1)
lg = param(3)
ht = param(4)
lg4= lg<<2
start = ( param(4) / param(5) ) * i
stop = ( param(4) / param(5) ) * (i + 1) +2
If i = (param(5) - 1) ; ndt
If stop <= param(4) : stop = param(4) - 2 : EndIf
EndIf
If stop > param(4)-2 : stop = param(4)-2 : EndIf
If start < 1 : start = 1 : EndIf
dif.f = 1 / Filter_convolution3x3_tab(9)
For y=start To stop
returnRGB(((y-1)*lg4) , 1)
returnRGB(((y-1)*lg4)+4,2)
returnRGB(((y-0)*lg4) , 4)
returnRGB(((y-0)*lg4)+4,5)
returnRGB(((y+1)*lg4) , 7)
returnRGB(((y+1)*lg4)+4,8)
For x=2 To lg-1
returnRGB(((((y-1)*lg)+x)*4) , 3)
returnRGB(((((y-0)*lg)+x)*4) , 6)
returnRGB(((((y+1)*lg)+x)*4) , 9)
ri=(r1*Filter_convolution3x3_tab(0)+r2*Filter_convolution3x3_tab(1)+r3*Filter_convolution3x3_tab(2)+r4*Filter_convolution3x3_tab(3)+r5*Filter_convolution3x3_tab(4)+r6*Filter_convolution3x3_tab(5)+r7*Filter_convolution3x3_tab(6)+r8*Filter_convolution3x3_tab(7)+r9*Filter_convolution3x3_tab(8))* dif + Filter_convolution3x3_tab(10)
gi=(g1*Filter_convolution3x3_tab(0)+g2*Filter_convolution3x3_tab(1)+g3*Filter_convolution3x3_tab(2)+g4*Filter_convolution3x3_tab(3)+g5*Filter_convolution3x3_tab(4)+g6*Filter_convolution3x3_tab(5)+g7*Filter_convolution3x3_tab(6)+g8*Filter_convolution3x3_tab(7)+g9*Filter_convolution3x3_tab(8))* dif + Filter_convolution3x3_tab(10)
bi=(b1*Filter_convolution3x3_tab(0)+b2*Filter_convolution3x3_tab(1)+b3*Filter_convolution3x3_tab(2)+b4*Filter_convolution3x3_tab(3)+b5*Filter_convolution3x3_tab(4)+b6*Filter_convolution3x3_tab(5)+b7*Filter_convolution3x3_tab(6)+b8*Filter_convolution3x3_tab(7)+b9*Filter_convolution3x3_tab(8))* dif + Filter_convolution3x3_tab(10)
ClampRGB(ri,gi,bi)
PokeL(cible_p+(y*lg*4)+(x-1)*4,(ri<<16+gi<<8+bi))
r1=r2:r2=r3:r4=r5:r5=r6:r7=r8:r8=r9
g1=g2:g2=g3:g4=g5:g5=g6:g7=g8:g8=g9
b1=b2:b2=b3:b4=b5:b5=b6:b7=b8:b8=b9
Next
Next
EndProcedure
;-------------------------------------------------------------------
;gestion des threads
Procedure Filter_convolution3x3(Filter_convolution3x3_source,Filter_convolution3x3_cible)
If Filter_convolution3x3_cible = 0 Or Filter_convolution3x3_source = 0 : ProcedureReturn : EndIf
Protected thread.i , Psource.i , Pcible.i , Pmask , lg , ht , i
thread=CountCPUs(#PB_System_CPUs)
If thread<2:thread=1:EndIf
Protected Dim tr.i(thread)
StartDrawing(ImageOutput(Filter_convolution3x3_source))
Psource = DrawingBuffer()
lg = ImageWidth(Filter_convolution3x3_source)
ht = ImageHeight(Filter_convolution3x3_source)
StopDrawing()
StartDrawing(ImageOutput(Filter_convolution3x3_cible))
Pcible = DrawingBuffer()
StopDrawing()
If Filter_convolution3x3_tab(9) = 0 : Filter_convolution3x3_tab(9) = 0.0000001 :EndIf ; pour eviter une division par 0
param(0)=Psource
param(1)=Pcible
param(3)=lg
param(4)=ht
param(5)=thread
For i=0 To thread-1 : tr(i)=0 : Next
For i=0 To thread-1
While tr(i)=0
tr(i)=CreateThread(@Filter_convolution3x3_thread(),i)
Wend
Next
For i=0 To thread-1
If IsThread(tr(i))>0 : WaitThread(tr(i)) : EndIf
Next
FreeArray(tr())
EndProcedure
;------------------------------------------------------------------
;-- image plugins
UseGIFImageDecoder()
UseJPEG2000ImageDecoder()
UseJPEG2000ImageEncoder()
UseJPEGImageDecoder()
UseJPEGImageEncoder()
UsePNGImageDecoder()
UsePNGImageEncoder()
UseTGAImageDecoder()
UseTIFFImageDecoder()
; charge une image et la convertie en 32bit
;-------------------------------------------------------------------
Procedure load_image(nom,file$)
Protected nom_p.i , temps_p.i , x.l , y.l , r.l,g.l,b.l , i.l
Protected lg.l , ht.l , depth.l , temps.i , dif.l , dif1.l
LoadImage(nom,file$)
If Not IsImage(nom) : ProcedureReturn 0 : EndIf
StartDrawing(ImageOutput(nom))
Depth=OutputDepth()
StopDrawing()
If Depth=24
CopyImage(nom,temps)
FreeImage(nom)
StartDrawing(ImageOutput(temps))
temps_p = DrawingBuffer()
lg = ImageWidth(temps)
ht = ImageHeight(temps)
dif = DrawingBufferPitch() - (lg*3)
StopDrawing()
CreateImage(nom,lg,ht,32)
StartDrawing(ImageOutput(nom))
nom_p = DrawingBuffer()
StopDrawing()
For y=0 To ht-1
For x=0 To lg-1
i = ((y*lg)+x)*3
r=PeekA(temps_p + i + 2 + dif1)
g=PeekA(temps_p + i + 1 + dif1)
b=PeekA(temps_p + i + 0 + dif1)
PokeL(nom_p + ((y*lg)+x)*4 , r<<16 + g<<8 + b)
Next
dif1 = dif1 + dif
Next
FreeImage(temps) ; supprime l'image 24bits
EndIf
ProcedureReturn 1
EndProcedure
;------------------------------------------------------------------
;-- programme test
If OpenWindow(0, 0, 0, 800, 800, "convolution3x3", #PB_Window_SystemMenu | #PB_Window_ScreenCentered | #PB_Window_SizeGadget | #PB_Window_MinimizeGadget | #PB_Window_MaximizeGadget)
CreateMenu(0, WindowID(0))
MenuTitle("Load")
MenuItem( 1, "Load Image")
MenuTitle("Save")
MenuItem( 2, "Save BMP")
;MenuItem( 3, "Save JPG")
MenuItem( 4, "Save Clipboard")
MenuTitle("Quit")
MenuItem( 5, "Quit")
Restore donnees
For y = 0 To 2
For x = 0 To 2
pos = 10+y*3+x
StringGadget(pos , x*40,y*20,39,19,"")
Read.f a.f
SetGadgetText(pos,Str(a))
Next
Next
StringGadget(19 , 130,10,39,19,"")
Read.f a.f : SetGadgetText(19,Str(a))
StringGadget(20 , 130,30,39,19,"")
Read.f a.f : SetGadgetText(20,Str(a))
Repeat
update = 0
Event = WindowEvent()
Select Event
Case #PB_Event_Gadget
Select EventGadget()
Case 10 To 20
update = 1
EndSelect
Case #PB_Event_Menu
Select EventMenu()
Case 1
source = 2
If IsImage(source) : FreeImage(source) : EndIf
If IsImage(cible) : FreeImage(cible) : cible = 0 : EndIf
If IsImage(mask) : FreeImage(mask) : mask = 0 : EndIf
file$ = OpenFileRequester("Image","","",0)
If Not Load_Image(source,file$)
source = 0
MessageRequester("load_image","erreur de chargement",#PB_MessageRequester_Ok | #PB_MessageRequester_Error)
Else
cible = 3
If IsImage(cible) : FreeImage(cible) : EndIf
CopyImage(source,cible)
StartDrawing(WindowOutput(0))
If IsImage(cible) : DrawImage(ImageID(cible),0,80) : EndIf
StopDrawing()
update = 1
EndIf
Case 2
nom$ = SaveFileRequester("Save BMP", "", "", 0)
If nom$ <> "" : SaveImage(cible, nom$+".bmp" ,#PB_ImagePlugin_BMP ) : EndIf
Case 4
SetClipboardImage(cible)
Case 5
quit = 1
EndSelect
EndSelect
If update = 1
Restore donnees
For i=0 To 10
t$=GetGadgetText(i+10)
b.f = ValD(t$)
Filter_convolution3x3_set(i,b)
Next
t=ElapsedMilliseconds()
Filter_convolution3x3(source,cible)
t=ElapsedMilliseconds() - t
StartDrawing(WindowOutput(0))
If IsImage(cible)
DrawImage(ImageID(cible),0,80)
;DrawText(750,5,Str(t)+" ")
EndIf
StopDrawing()
EndIf
Until Event = #PB_Event_CloseWindow Or quit=1
CloseWindow(0)
EndIf
DataSection
donnees:
Data.f -4,1,1
Data.f 1,-10,1
Data.f 1,1,9
Data.f 1,0,0
EndDataSection