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 getColor avec 2 procedure 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)]
Gratteur
Messages : 147
Inscription : ven. 22/avr./2005 23:02

Message par Gratteur »

C’est très bien tout ça mais l’image met aussi 10 fois plus de temps à se générer ;p.
Backup
Messages : 14526
Inscription : lun. 26/avr./2004 0:40

Message par Backup »

il faut que tu mette #Nb = 50 (ligne 64 ) pour te rendre compte
et regarde bien les milliseconde affichés en bas de la petite fenetre

ligne 87 If 0 <--- methode avec les plots regarde le temps (3ms calcul et 113 ms de dessin)

change par

ligne 87 If 1 <--- methode au soldat et regarde le temps !! (4ms de calcul 8ms de dessin !!!! ) <-- beaucoup plus rapide !!! :D
Gratteur
Messages : 147
Inscription : ven. 22/avr./2005 23:02

Message par Gratteur »

C'est pas ce que je veux dire. Lorsque tu applique un effet sur une image tu récupère d'abord les couleurs de l'image avant de les modifier et la plupart du temps tu peux dessiner ton image dans la même boucle. Là ça te bouffe deux fois plus de mémoire (donc plantage pour les très grosses images) et le deuxième algo est souvent défavorisé.
Bon ok je chipote (parcequ'il y a un truc qui me chiffonne dans cet exemple) il est bien plus rapide quand même ;p
Bravo Soldat.
Répondre