filtre noir et blanc

Pour discuter de l'assembleur
manababel
Messages : 135
Inscription : jeu. 14/mai/2020 7:40

filtre noir et blanc

Message par manababel »

Bonjour, il se peut que ce sujet ne soit pas dans la bonne section.
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
Dernière modification par manababel le dim. 24/mai/2020 13:29, modifié 1 fois.
Avatar de l’utilisateur
Ar-S
Messages : 9472
Inscription : dim. 09/oct./2005 16:51
Contact :

Re: filtre noir et blanc

Message par Ar-S »

Bonjour.
Dommage qu'il faille d'abord convertir l'image en niveau de gris. Par contre le traitement est encore vache de rapide :)

En l'etat, ta procedure Load_Image générera une erreur en cas d'annulation du chargement d'une image, car le isImage n'empêchera pas ton prog de tester le resizeimage sur une image qui n'existe pas.
Ajoute un procedureReturn 1 dans la proce après ton FreeMemory(cible_p)

et fais la vérif dans l'appel de la proce L226

Code : Tout sélectionner

If Load_Image(source,file$) = 0 : Debug " annulée " : End : EndIf  ; <- commande differente de "LOADIMAGE"
note :
Pour la conversion en gris tu additionnes tes 3 constantes R,G,B que tu divises par 3 pour obtenir le gris.

Code : Tout sélectionner

Gray = (R1+G1+B1) / 3
pixel=RGB(Gray ,Gray ,Gray )
~~~~Règles du forum ~~~~
⋅.˳˳.⋅ॱ˙˙ॱ⋅.˳Ar-S ˳.⋅ॱ˙˙ॱ⋅.˳˳.⋅
W11x64 PB 6.x
Section HORS SUJET : ICI
LDV MULTIMEDIA : Dépannage informatique & mes Logiciels PB
UPLOAD D'IMAGES : Uploader des images de vos logiciels
manababel
Messages : 135
Inscription : jeu. 14/mai/2020 7:40

Re: filtre noir et blanc

Message par manababel »

merci

C'est corrigé.
Répondre