Page 1 sur 1

Travailler sur une image 10 fois plus vite

Publié : mar. 31/août/2004 18:19
par Le Soldat Inconnu
Salut,

j'ai complété ma lib ColorEffect avec 2 procedures qui permmettent de travailler environ 10 fois plus vite sur une image.

Dans ce sens, je veux dire que j'ai testé en modifiant chaque pixel de l'image par une formule, et avec ma procedure, on va 10 fois plus vite qu'avec des plots

la lib est sur mon site (elle contient un début de programme à la photoshop pour appliquer des effets sur une image)

Pour ceux qui ne veulent pas installé ma lib, voici un exemple

Code : Tout sélectionner

; Auteur : Le Soldat Inconnu
; Version de PB : 3.90
; 
; Explication du programme :
; Exemple qui montre comment travailler rapidement sur une image.
; Voir la librairie ColorEffect sur mon site http://perso.wanadoo.fr/lesoldatinconnu/

Procedure.l SetImageBits2(ImageID, HList) ; Transfert d'un tableau vers une image
  Protected bmi.BITMAPINFO, Hdc.l, Resultat, Mem, n, nn, bm.BITMAP
  
  Resultat = 0
  
  GetObject_(ImageID, SizeOf(BITMAP), @bm.BITMAP) ; pour récupérer la taille de l'image
  
  ; On donne les information nécessaires
  bmi\bmiHeader\biSize = SizeOf(BITMAPINFOHEADER)
  bmi\bmiHeader\biWidth = bm\bmWidth
  bmi\bmiHeader\biHeight = bm\bmHeight
  bmi\bmiHeader\biPlanes = 1
  bmi\bmiHeader\biBitCount = 32
  bmi\bmiHeader\biCompression = #BI_RGB
  
  ; On crée une zone mémoire tampon qui va permettre de convertir la liste dans le format adéquat
  Mem = AllocateMemory(bm\bmWidth * bm\bmHeight * 4)
  If Mem
    
    ; On convertit le contenu du tableau dans le bon format et dans le bon ordre
    For n = 0 To bm\bmHeight - 1
      For nn = 0 To bm\bmWidth - 1
        CopyMemory(HList + n * 4 + nn * bm\bmHeight * 4, Mem + nn * 4 + (bm\bmHeight - 1 - n) * bm\bmWidth * 4 + 2, 1)
        CopyMemory(HList + n * 4 + nn * bm\bmHeight * 4 + 1, Mem + nn * 4 + (bm\bmHeight - 1 - n) * bm\bmWidth * 4 + 1, 1)
        CopyMemory(HList + n * 4 + nn * bm\bmHeight * 4 + 2, Mem + nn * 4 + (bm\bmHeight - 1 - n) * bm\bmWidth * 4, 1)
      Next
    Next
    
    ; On édite limage
    Hdc = CreateCompatibleDC_(GetDC_(ImageID))
    If Hdc
      SetDIBits_(Hdc, ImageID, 0, bm\bmHeight, Mem, @bmi, #DIB_RGB_COLORS) ; On envoie le tableau dans l'image
      ReleaseDC_(0, Hdc)
      Resultat = ImageID
    EndIf
    
    FreeMemory(Mem) ; on libère la mémoire
  EndIf
  
  ProcedureReturn Resultat
EndProcedure


;- Début du code

OpenWindow(0, 0, 0, 310, 258 + 25, #PB_Window_ScreenCentered | #PB_Window_SystemMenu, "Test")
CreateGadgetList(WindowID())

CreateImage(0, 300, 258)

ImageGadget(0, 4, 4, 0, 0, ImageID())

Couleur1 = 50
Couleur2 = 100
Couleur3 = 255

#Nb = 20
Dim Nuance.l(299, 257)

Temps1 = ElapsedMilliseconds()

; On dessine l'image dans une liste
For n = 1 To #Nb ; la boucle permet de répéter le calcul plusieur fois afin d'avoir une estimation du temps plus précise
  For i = 0 To 297
    nb.f = 1 - i / 297
    C1.f = Couleur1 + (255 - Couleur1) * nb
    C2.f = Couleur2 + (255 - Couleur2) * nb
    C3.f = Couleur3 + (255 - Couleur3) * nb
    
    For ii = 0 To 255
      nb.f = 1 - ii / 255
      Nuance(1 + i, 1 + ii) = RGB(C1 * nb, C2 * nb, C3 * nb)
    Next
  Next
Next

Temps2 = ElapsedMilliseconds()

For n = 1 To #Nb ; la boucle permet de répéter le calcul plusieur fois afin d'avoir une estimation du temps plus précise
  If 1 ; Ici mettre 1 pour ma méthode et 0 pour la méthode avec des plots, regardez bien la différence de rapidité entre les 2 méthodes
    SetImageBits2(UseImage(0), @Nuance())
  Else
    UseImage(0)
    StartDrawing(ImageOutput())
    For i = 0 To 298
      For ii = 0 To 255
        Plot(i + 1, ii + 1, Nuance(i + 1, ii + 1))
      Next
    Next
    StopDrawing()
  EndIf
Next

Temps3 = ElapsedMilliseconds()

; On affiche l'image
SetGadgetState(0, UseImage(0))

; on affiche les temps de calcul
TextGadget(1, 0, 265, 310, 15, Str((Temps2 - Temps1) / #Nb) + " ms de calcul / " + Str((Temps3 - Temps2) / #Nb) + " ms pour dessiner", #PB_Text_Center)

Repeat
  
Until WaitWindowEvent() = #PB_Event_CloseWindow

Publié : mar. 31/août/2004 20:11
par Flype
trop fort... impressionnant :twisted:

Publié : mar. 31/août/2004 22:08
par Oliv
J'ai pas le temps de tester mais je te crois, ça va m'être très utile dans peu de temps :D merci

Publié : mar. 31/août/2004 22:26
par garzul
Help j'ai pas trop compri 8O

Publié : mar. 31/août/2004 22:53
par Flype
garzul,
quand on dessine une image point après point, pixel après pixel, comme c'est le cas dans cet exemple, on doit tout simplement utiliser la fonction purebasic point(x,y,couleur).
soldat inconnu montre une fonction à lui qui va beaucoup plus vite que celle fournit avec purebasic...

merci encore donc !

Publié : mar. 31/août/2004 23:34
par garzul
:D Ouais je me disais aussi que j'avais bien comprie 8O :lol: Merci quand meme flype ^^

Publié : mer. 01/sept./2004 8:37
par Backup
y a plus qu'a suggerer a Fred de revoir sa copie !! :lol:

Publié : mer. 01/sept./2004 10:09
par Le Soldat Inconnu
ça ne marche que si il y plein de plot, pour un seul, le gain de temps ne doit pas ête flagrant car il y a un temps de conversion entre les données win et les données sur lesquelles nous avons l'habitude de travailler

en clair, vous voyez ce bout de code :

Code : Tout sélectionner

; On convertit le contenu du tableau dans le bon format et dans le bon ordre 
    For n = 0 To bm\bmHeight - 1 
      For nn = 0 To bm\bmWidth - 1 
        CopyMemory(HList + n * 4 + nn * bm\bmHeight * 4, Mem + nn * 4 + (bm\bmHeight - 1 - n) * bm\bmWidth * 4 + 2, 1) 
        CopyMemory(HList + n * 4 + nn * bm\bmHeight * 4 + 1, Mem + nn * 4 + (bm\bmHeight - 1 - n) * bm\bmWidth * 4 + 1, 1) 
        CopyMemory(HList + n * 4 + nn * bm\bmHeight * 4 + 2, Mem + nn * 4 + (bm\bmHeight - 1 - n) * bm\bmWidth * 4, 1) 
      Next 
    Next
il permet de convertir les données dans le format qu'on a l'habitude de rencontrer à savoir le point x=0 et y=0 en haut à gauche de l'image et le format RGB pour les couleurs

en le retirant, on va encore plus vite mais ça pose quelque problème mental pour arriver à se servir du tableau par la suite.

car voici les problèmes qu'on va rencontrer :
- les x et les y sont inversés
- les y vont du bas vers le haut (le y=0 est en bas de l'image)
- le rouge et le bleu sont inversés, on a la couleur BGR au lieu de RGB

je me passe de ce morceau de code sur ma lib GetColor par exemple
et dans ce cas, le transfert de l'image ne prends que 6-7 ms sur mon 900mhz (donc encore 3 fois plus vite :D )

donc si vous voulez aller encore plus vite faut supprimer ça mais après, faut se torturer les méninges pour remettre tout ça dans l'ordre :wink:

Publié : ven. 03/sept./2004 13:29
par ZapMan
Le Soldat Inconnu a écrit :ça ne marche que si il y plein de plot, pour un seul, le gain de temps ne doit pas ête flagrant car il y a un temps de conversion entre les données win et les données sur lesquelles nous avons l'habitude de travailler
S'il n'y a qu'un seul plot à faire, on se moque un peu de gagner du temps. S'il y en a plein à faire, on tient absolument à gagner du temps. Donc ta nouvelle instruction est préférable dans tous les cas.

Chapeau pour la performance, c'est bluffant.

Publié : lun. 06/sept./2004 19:08
par erix14
Je me suis amusé à me torturer les méninges, pour voir le temps qu'on pouvait obtenir avec l'optimisation... :lol:
Merci le soldat inconnu :wink: , c'est très rapide :lol:

Code : Tout sélectionner

Structure Couleur
          b.b
          g.b
          r.b
          a.b
EndStructure
;- Début du code 

OpenWindow(0, 0, 0, 310, 258 + 25, #PB_Window_ScreenCentered | #PB_Window_SystemMenu, "Test") 
CreateGadgetList(WindowID()) 

CreateImage(0, 300, 258) 
MemNuance = AllocateMemory(300 * 258 * 4) 

ImageGadget(0, 4, 4, 0, 0, ImageID()) 

couleur1 = 50 
couleur2 = 100 
couleur3 = 255 

couleur1a = 255 - 50 
couleur2a = 255 - 100 
couleur3a = 255 - 255 

#Nb = 20 

Temps1 = ElapsedMilliseconds() 
d.f = 1/299
; On dessine l'image dans une liste 
For n = 1 To #Nb ; la boucle permet de répéter le calcul plusieur fois afin d'avoir une estimation du temps plus précise 
          *MonPtr.Couleur = MemNuance
          For i = 0 To 257
                    nb1.f = i / 257
                    nb.f = 1
                    For ii = 0 To 299 
                              *MonPtr\r = (couleur1 + couleur1a * nb) * nb1 
                              *MonPtr\g = (couleur2 + couleur2a * nb) * nb1
                              *MonPtr\b = (couleur3 + couleur3a * nb) * nb1
                              *MonPtr + 4
                              nb - d
                    Next 
          Next 
Next 

Temps2 = ElapsedMilliseconds() 

For n = 1 To #Nb ; la boucle permet de répéter le calcul plusieur fois afin d'avoir une estimation du temps plus précise 
                    GetObject_(UseImage(0), SizeOf(BITMAP), @bm.BITMAP) ; pour récupérer la taille de l'image 
                    
                    ; On donne les information nécessaires 
                    bmi.BITMAPINFO\bmiHeader\biSize = SizeOf(BITMAPINFOHEADER) 
                    bmi\bmiHeader\biWidth = bm\bmWidth 
                    bmi\bmiHeader\biHeight = bm\bmHeight 
                    bmi\bmiHeader\biPlanes = 1 
                    bmi\bmiHeader\biBitCount = 32 
                    bmi\bmiHeader\biCompression = #BI_RGB 
                    
                              ; On édite limage 
                              hDC = CreateCompatibleDC_(GetDC_(UseImage(0))) 
                              If hDC 
                                        SetDIBits_(hDC, UseImage(0), 0, bm\bmHeight, MemNuance, @bmi, #DIB_RGB_COLORS) ; On envoie le tableau dans l'image 
                                        ReleaseDC_(0, hDC) 
                              EndIf 
                    Next

Temps3 = ElapsedMilliseconds() 

; On affiche l'image 
SetGadgetState(0, UseImage(0)) 

; on affiche les temps de calcul 
TextGadget(1, 0, 265, 310, 15, Str((Temps2 - Temps1) / #Nb) + " ms de calcul / " + Str((Temps3 - Temps2) / #Nb) + " ms pour dessiner", #PB_Text_Center) 

Repeat 
          
Until WaitWindowEvent() = #PB_Event_CloseWindow

Publié : lun. 06/sept./2004 21:55
par Le Soldat Inconnu
pas bête du tout, ton astuce pour inverser les RGB en BGR :D

Publié : mar. 07/sept./2004 20:47
par erix14
:D

Publié : sam. 01/janv./2005 14:22
par Le Soldat Inconnu
bon, j'ai optimiser le code et ça va encore 2 fois plus vite

(16 fois plus vite pour envoyer vers l'image et 28 fois plus pour récupérer l'image comparé au plot et point)

Vous trouverez ça dans ma lib Effect sur mon site (attention, elle remplace la lib ColorEffet donc il faut la supprimer)
Voir ici pour les autres fonctions de la lib :
http://purebasic.hmt-forum.com/viewtopi ... 7&start=15