il est multi-thread et utilise des nombres flottants
les pixels du bord de l'image ne sont pas traités
utilisez des images de petites taille , cette version demande beaucoup de ressources au processeur ( ex: 512x512 max)
Code : Tout sélectionner
;-------------------------------------------------------------------
Global Dim Filter_convolution5x5_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_convolution5x5_set(v1,v2.f)
If v1<0 Or v1>26 : ProcedureReturn : EndIf
Filter_convolution5x5_tab(v1) = v2
EndProcedure
; programme principal
Procedure Filter_convolution5x5_thread(i)
Protected Dim r.f(25)
Protected Dim g.f(25)
Protected Dim b.f(25)
Protected x.l , y.l , pixel.l
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) - 3 : EndIf
EndIf
If stop > param(4)-2 : stop = param(4)-3 : EndIf
If start < 2 : start = 2 : EndIf
dif.f = 1 / Filter_convolution5x5_tab(25)
For y=start To stop
For i=1 To 4
returnRGB(((y-2)*lg4)+i*4 , i)
returnRGB(((y-1)*lg4)+i*4 , i+6)
returnRGB(((y-0)*lg4)+i*4 , i+11)
returnRGB(((y+1)*lg4)+i*4 , i+16)
returnRGB(((y+2)*lg4)+i*4 , i+21)
Next
For x=4 To lg-1
returnRGB(((((y-2)*lg)+x)*4) , 5)
returnRGB(((((y-1)*lg)+x)*4) , 10)
returnRGB(((((y+0)*lg)+x)*4) , 15)
returnRGB(((((y+1)*lg)+x)*4) , 20)
returnRGB(((((y+2)*lg)+x)*4) , 25)
ri = 0 : gi = 0 : bi = 0
For i=1 To 25
ri = ri + r(i) * Filter_convolution5x5_tab(i-1)
gi = gi + g(i) * Filter_convolution5x5_tab(i-1)
bi = bi + b(i) * Filter_convolution5x5_tab(i-1)
r(i) = r(i+1)
g(i) = g(i+1)
b(i) = b(i+1)
Next
ri = ri * dif + Filter_convolution5x5_tab(26)
gi = gi * dif + Filter_convolution5x5_tab(26)
bi = bi * dif + Filter_convolution5x5_tab(26)
ClampRGB(ri,gi,bi)
PokeL(cible_p+(y*lg*4)+(x-2)*4,(ri<<16+gi<<8+bi))
Next
Next
EndProcedure
;-------------------------------------------------------------------
;gestion des threads
Procedure Filter_convolution5x5(Filter_convolution5x5_source,Filter_convolution5x5_cible)
If Filter_convolution5x5_cible = 0 Or Filter_convolution5x5_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_convolution5x5_source))
Psource = DrawingBuffer()
lg = ImageWidth(Filter_convolution5x5_source)
ht = ImageHeight(Filter_convolution5x5_source)
StopDrawing()
StartDrawing(ImageOutput(Filter_convolution5x5_cible))
Pcible = DrawingBuffer()
StopDrawing()
If Filter_convolution5x5_tab(25) = 0 : Filter_convolution5x5_tab(25) = 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_convolution5x5_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 4
For x = 0 To 4
pos = 10+y*5+x
StringGadget(pos , x*40,y*20,39,19,"")
Read.f a.f
SetGadgetText(pos,Str(a))
Next
Next
StringGadget(35 , 210,10,39,19,"")
Read.f a.f : SetGadgetText(35,Str(a))
StringGadget(36 , 210,30,39,19,"")
Read.f a.f : SetGadgetText(36,Str(a))
Repeat
update = 0
Event = WindowEvent()
Select Event
Case #PB_Event_Gadget
Select EventGadget()
Case 10 To 36
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,100) : 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 26
t$=GetGadgetText(i+10)
b.f = ValD(t$)
Filter_convolution5x5_set(i,b)
Next
t=ElapsedMilliseconds()
Filter_convolution5x5(source,cible)
t=ElapsedMilliseconds() - t
StartDrawing(WindowOutput(0))
If IsImage(cible)
DrawImage(ImageID(cible),0,100)
;DrawText(750,5,Str(t)+" ")
EndIf
StopDrawing()
EndIf
Until Event = #PB_Event_CloseWindow Or quit=1
CloseWindow(0)
EndIf
DataSection
donnees:
Data.f -2,-2,-2,-2,-2
Data.f -2,-1,-1,-1, 2
Data.f -2,-1, 5, 1, 2
Data.f -2, 1, 1, 1, 2
Data.f -2, 2, 2, 2, 2
Data.f 1,0
EndDataSection