Travailler sur une image 10 fois plus vite

Vous avez développé un logiciel en PureBasic et vous souhaitez le faire connaitre ?
Le Soldat Inconnu
Messages : 4312
Inscription : mer. 28/janv./2004 20:58
Localisation : Clermont ferrand OU Olsztyn
Contact :

Travailler sur une image 10 fois plus vite

Message 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
Je ne suis pas à moitié Polonais mais ma moitié est polonaise ... Vous avez suivi ?

[Intel quad core Q9400 2.66mhz, ATI 4870, 4Go Ram, XP (x86) / 7 (x64)]
Avatar de l’utilisateur
Flype
Messages : 2431
Inscription : jeu. 29/janv./2004 0:26
Localisation : Nantes

Message par Flype »

trop fort... impressionnant :twisted:
Image
Oliv
Messages : 2117
Inscription : mer. 21/janv./2004 18:39

Message 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
garzul
Messages : 683
Inscription : mer. 26/mai/2004 0:33

Message par garzul »

Help j'ai pas trop compri 8O
Avatar de l’utilisateur
Flype
Messages : 2431
Inscription : jeu. 29/janv./2004 0:26
Localisation : Nantes

Message 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 !
Image
garzul
Messages : 683
Inscription : mer. 26/mai/2004 0:33

Message par garzul »

:D Ouais je me disais aussi que j'avais bien comprie 8O :lol: Merci quand meme flype ^^
Backup
Messages : 14526
Inscription : lun. 26/avr./2004 0:40

Message par Backup »

y a plus qu'a suggerer a Fred de revoir sa copie !! :lol:
Le Soldat Inconnu
Messages : 4312
Inscription : mer. 28/janv./2004 20:58
Localisation : Clermont ferrand OU Olsztyn
Contact :

Message 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:
Je ne suis pas à moitié Polonais mais ma moitié est polonaise ... Vous avez suivi ?

[Intel quad core Q9400 2.66mhz, ATI 4870, 4Go Ram, XP (x86) / 7 (x64)]
Avatar de l’utilisateur
ZapMan
Messages : 460
Inscription : ven. 13/févr./2004 23:14
Localisation : France
Contact :

Message 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.
Tout obstacle est un point d'appui potentiel.

Bibliothèques PureBasic et autres codes à télécharger :https://www.editions-humanis.com/downlo ... ads_FR.htm
erix14
Messages : 480
Inscription : sam. 27/mars/2004 16:44
Contact :

Message 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
Le Soldat Inconnu
Messages : 4312
Inscription : mer. 28/janv./2004 20:58
Localisation : Clermont ferrand OU Olsztyn
Contact :

Message par Le Soldat Inconnu »

pas bête du tout, ton astuce pour inverser les RGB en BGR :D
Je ne suis pas à moitié Polonais mais ma moitié est polonaise ... Vous avez suivi ?

[Intel quad core Q9400 2.66mhz, ATI 4870, 4Go Ram, XP (x86) / 7 (x64)]
erix14
Messages : 480
Inscription : sam. 27/mars/2004 16:44
Contact :

Message par erix14 »

:D
Le Soldat Inconnu
Messages : 4312
Inscription : mer. 28/janv./2004 20:58
Localisation : Clermont ferrand OU Olsztyn
Contact :

Message 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
Je ne suis pas à moitié Polonais mais ma moitié est polonaise ... Vous avez suivi ?

[Intel quad core Q9400 2.66mhz, ATI 4870, 4Go Ram, XP (x86) / 7 (x64)]
Répondre