Ce n'est pas un tutoriel , une application et ni un "trucs et astuces".
C'est juste un programme optimisé en ASM.
juste un "bout de code", mais fonctionnel
Si ça vous intéresse, j'en posterais d'autres.( programme lie aux filtres graphiques)
ca permet de convertir une image couleur en "noir et blanc" ( enfin presque).
Étant donné que le programme convertie chaque couleur indépendamment des unes des autres, il faudra convertir l'image en niveau de gris avant .
il y a surement des erreurs dans se programme , n'hésitez pas de me les indiquer si vous en remarquez..
il y a deux programmes.
Ce sont les mêmes programmes , un en basic (Pour la compréhension),
le second optimisé en ASM
Code : Tout sélectionner
EnableExplicit
; charge une image et la convertie en 32bit
;-------------------------------------------------------------------
Procedure load_image(nom,file$)
Protected source_p , cible_p , s.q
Protected lg.q , ht.q , taille.q , depth.q
LoadImage(nom,file$)
If Not IsImage(nom) : ProcedureReturn 0 : EndIf
StartDrawing(ImageOutput(nom))
source_p = DrawingBuffer()
ht = ImageHeight(nom)
lg = ImageWidth(nom)
Depth=OutputDepth()
StopDrawing()
Debug lg
Debug ht
If Depth=24
taille=lg*ht
cible_p=AllocateMemory(taille*4)
Dim save.q(4)
s=@save()
EnableASM
!mov rax,[p.v_s]
!mov [rax],rcx
!mov [rax+8],rdx
!mov [rax+16],r8
!mov rcx,[p.v_source_p]
!mov rdx,[p.v_cible_p]
!mov r8,[p.v_taille]
!sub r8,1 ; <---------------- ????
!copy_boucle24:
!mov eax,[rcx]
!mov [rdx],eax
!add rcx,3
!add rdx,4
!dec r8
!jnz copy_boucle24
!mov rax,[p.v_s]
!mov rcx,[rax]
!mov rdx, [rax+8]
!mov r8,[rax+16]
DisableASM
FreeArray(save())
FreeImage(nom) ; supprime l'image 24bits
CreateImage(nom,lg,ht,32)
StartDrawing(ImageOutput(nom))
source_p = DrawingBuffer()
StopDrawing()
CopyMemory( cible_p , source_p , taille*4 )
FreeMemory(cible_p)
EndIf
ProcedureReturn 1
EndProcedure
; partie du programme à modifier pour adapter se programme au votre
; convertie les "IDs" des images en pointer d'adresse
; test si les images sont en 32bits et de la meme taille
;-------------------------------------------------------------------
Macro sp(source,cible)
Protected Depth.q , lg.q , ht.q , lg1.q , ht1.q , taille.q
Protected cible_p.q , source_p.q
StartDrawing(ImageOutput(cible))
cible_p = DrawingBuffer()
ht1 = ImageHeight(cible)
lg1 = ImageWidth(cible)
Depth=OutputDepth()
StopDrawing()
If depth<>32 : ProcedureReturn : EndIf
StartDrawing(ImageOutput(source))
source_p = DrawingBuffer()
ht = ImageHeight(source)
lg = ImageWidth(source)
Depth=OutputDepth()
StopDrawing()
If depth<>32 : ProcedureReturn : EndIf
If lg<>lg1 Or ht<>ht1 : ProcedureReturn : EndIf
EndMacro
;-------------------------------------------------------------------
Procedure Filter_BlackAndWhite_pb(source.q,cible.q,seuil.q=127)
Protected long.q , i.q , pixel.l
Protected r1 , g1 , b1 , r2 , g2 , b2
sp(source,cible)
long = lg * ht * 4 ; taille de l'image en memoire ( longueur * hauteur * 4x8bits(32bits) )
For i=0 To (long-1) Step 4 ; ( 4 = RGBA )
pixel=PeekL(source_p+i)
r1 = Red(pixel)
g1 = Green(pixel)
b1 = Blue(pixel)
r2=0 : g2=0 : b2=0
If r1>=seuil : r2 = 255 : EndIf ; (R)
If g1>=seuil : g2 = 255 : EndIf ; (G)
If b1>=seuil : b2 = 255 : EndIf ; (B)
; couleur 'A' non traité , corespond à la couche alpha
pixel=RGB(r2,g2,b2)
PokeL(cible_p+i,pixel)
Next
EndProcedure
;-------------------------------------------------------------------
Procedure Filter_BlackAndWhite(source.q,cible.q,seuil.q=127)
Protected long.q , s.q , var , i , pixel.l , pos.q
Protected r1.a , g1 , b1 , r2 , g2 , b2
sp(source,cible)
long = lg * ht
Dim save.q(14)
s=@save()
EnableASM
!mov rax,[p.v_s] ; sauvegarde des registres
!mov [rax],rsi
!mov [rax+16],rdi
!mov [rax+32],rdx
!movdqu [rax+48],xmm0
!movdqu [rax+64],xmm1
!movdqu [rax+80],xmm2
!movdqu [rax+96],xmm3
!mov rsi,[p.v_source_p]
!mov rdi,[p.v_cible_p]
!mov rdx,[p.v_long]
!shr rdx,2
!xor rax,rax
!mov al,127
!movd xmm3,eax
!mov rax,$10101
!movd xmm2,eax
!pmulld xmm3,xmm2 ; 8bits -> 4x8bits (=32bits) ( 127 x $10101 )
!pshufd xmm3,xmm3,0 ; 32bits -> 4x32bits (=128bits) ( copy 1 vers 4 )
!xor rax,rax
!mov al,[p.v_seuil]
!sub al,127
!movd xmm1,eax
!mov rax,$10101
!movd xmm2,eax
!pmulld xmm1,xmm2 ; 8bits -> 4x8bits (=32bits)
!pshufd xmm1,xmm1,0 ; 32bits -> 4x32bits (=128bits)
!BlackAndWhite_01:
!movdqu xmm0,[rsi] ; charge 4 pixels (128bits) (a1 r1 g1 b1 , r2... , r3 ... , a4 r4 g4 b4 )
!psubb xmm0,xmm3 ; soustraction pour passer de (0 à 255) -> (-127 à 128)
!pcmpgtb xmm0,xmm1 ; compare des valeurs entre -127 et 128 ( if xmm0 > xmm 1 ) return 255 else return 0
!movdqu [rdi],xmm0
!add rsi,16
!add rdi,16
!dec rdx
!jnz BlackAndWhite_01
!mov rax,[p.v_s] ; restauration des registres
!mov rsi,[rax]
!mov rdi, [rax+16]
!mov rdx,[rax+32]
!movdqu xmm0,[rax+48]
!movdqu xmm1,[rax+64]
!movdqu xmm2,[rax+80]
!movdqu xmm3,[rax+96]
DisableASM
FreeArray(save())
; si l'image n'ai pas un multiple de 4 (lg*ht) , les derniers pixels ne sont pas converti ci-dessus
; ci-desous , la partie qui convertie les derniers pixels ( 3 pixel aux maximum a convertir )
var = Mod( long , 4 )
If var > 0
pos=((lg*ht)-1)*4
For i=(pos - var) To pos
pixel=PeekL(source+i)
r1 = Red(pixel)
g1 = Green(pixel)
b1 = Blue(pixel)
r2=0 : g2=0 : b2=0
If r1>=seuil : r2 = 255 : EndIf
If g1>=seuil : g2 = 255 : EndIf
If b1>=seuil : b2 = 255 : EndIf
pixel=RGB(r2,g2,b2)
PokeL(cible+i,pixel)
Next
EndIf
EndProcedure
;-------------------------------------------------------------------
UseJPEGImageDecoder()
UsePNGImageDecoder()
Global imgx=1200
Global imgy=800
If OpenWindow(0, 0, 0, imgx, imgy, "b&w", #PB_Window_SystemMenu | #PB_Window_ScreenCentered)
Define source.q , cible.q , t.q , file$ , i
file$ = OpenFileRequester("Image","","",0)
source=10
cible=20
If Not Load_Image(source,file$) ; <- commande differente de "LOADIMAGE"
MessageRequester("load_image","erreur de chargement",#PB_MessageRequester_Ok | #PB_MessageRequester_Error)
End
EndIf
ResizeImage(source,imgx,imgy,#PB_Image_Smooth)
CreateImage(cible,imgx,imgy,32) ; l'image doit entre en mode 32bits
t=ElapsedMilliseconds()
Filter_BlackAndWhite(source,cible,127)
t=ElapsedMilliseconds()-t
StartDrawing(WindowOutput(0))
DrawImage(ImageID(cible),0,0)
DrawText(5,5,Str(t))
StopDrawing()
Repeat : Until WaitWindowEvent() = #PB_Event_CloseWindow
EndIf