Page 4 sur 8

Publié : mar. 15/févr./2005 15:45
par Le Soldat Inconnu
Oui, on cherche à optimiser ma lib Effect, plus précisement les fonctions de rotation de symétrie.

tu lance le code, tu regarde le temps obtenu, tu bidouille et si tu va plus vite, tu as gagné :lol:

Publié : mar. 15/févr./2005 18:08
par djes
Ok! La dernière version est celle sur le forum je suppose? Bon, je m'y mets! On peut reprendre les idées de ses petits camarades?

Publié : mar. 15/févr./2005 19:03
par Le Soldat Inconnu
La dernière est celle de mon dernier post (du moins la plus rapide pour l'instant) :D

Toutes les idées sont les bienvenue au niveau des fonctions a ajouté ou a améliorée.

je pense déjà que je vais ajouté des fonctions pour tracé des cercles ou des lignes avec lissage :wink:

Publié : mar. 15/févr./2005 19:22
par djes
Si tu utilises du lissage, n'oublie surtout pas l'alpha, stp...

Publié : mar. 15/févr./2005 19:49
par Le Soldat Inconnu
Pas bête :D

Publié : mar. 15/févr./2005 20:16
par djes
Ben ouais sinon on pourra jamais faire un photoshop like!

Publié : mer. 16/févr./2005 1:56
par djes
Bon voilà ma première version modifiée.

C'est une version avec des entiers que je vous montre car c'est la seule dont la vitesse se rapproche de celle de soldat... Par contre, j'avais fait une version avec des flottants, contenant moins d'instructions et qui était plus lente. Il y a clairement un problème d'ALIGNEMENT du code dans pure (ou peut-être d'allocation de registres), et je ne sais pas comment le résoudre! Enfin j'essaierai encore demain ;)

Code : Tout sélectionner

#Pi.f=3.14159265

ProcedureDLL.l RotateImageEx2(ImageID, Angle.f) ; Rotation d'une image d'un angle en °
  Protected bmi.BITMAPINFO, bmi2.BITMAPINFO, Hdc.l, NewImageID, Mem, n, nn, bm.BITMAP, Temp1, Temp2

  DefType.f x1,y1
  DefType.l x1b,y1b,fxl,fyl,f00l,f01l,f10l,f11l

 
  Angle = Angle * #Pi / 180 ; On convertit en radian
 
  GetObject_(ImageID, SizeOf(BITMAP), @bm.BITMAP)
 
  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
 
  bmi2\bmiHeader\biSize = SizeOf(BITMAPINFOHEADER)
  bmi2\bmiHeader\biWidth = Int(bm\bmWidth * Abs(Cos(Angle)) + bm\bmHeight * Abs(Sin(Angle)) + 0.5)
  bmi2\bmiHeader\biHeight = Int(bm\bmHeight * Abs(Cos(Angle)) + bm\bmWidth * Abs(Sin(Angle)) + 0.5)
  bmi2\bmiHeader\biPlanes = 1
  bmi2\bmiHeader\biBitCount = 32
  bmi2\bmiHeader\biCompression = #BI_RGB
 
  Mem = AllocateMemory(bm\bmWidth * bm\bmHeight * 4)
  If Mem
    Mem2 = AllocateMemory(bmi2\bmiHeader\biWidth * bmi2\bmiHeader\biHeight * 4)
    If Mem2
     
      Hdc = CreateCompatibleDC_(GetDC_(ImageID))
      If Hdc
        GetDIBits_(Hdc, ImageID, 0, bm\bmHeight, Mem, @bmi, #DIB_RGB_COLORS) ; on envoie la liste dans l'image
        ReleaseDC_(0, Hdc)
      EndIf
     
      CX1 = (bm\bmWidth - 1) * 512 / 2
      CY1 = (bm\bmHeight - 1) * 512 / 2
      CX2 = (bmi2\bmiHeader\biWidth - 1) * 512 / 2
      CY2 = (bmi2\bmiHeader\biHeight - 1) * 512 / 2
      
      ;un seul Dim est surement plus rapide que 2
      If bmi2\bmiHeader\biWidth>bmi2\bmiHeader\biHeight
        Dim tabxy2.f(bmi2\bmiHeader\biWidth,4)
      Else
        Dim tabxy2.f(bmi2\bmiHeader\biHeight,4)
      EndIf
      x2.f=-CX2

      sin.f=Sin(angle)
      cos.f=Cos(angle)
      For i = 0 To bmi2\bmiHeader\biWidth - 1
        tabxy2(i,0)=CX1+x2*cos
        tabxy2(i,1)=CY1+x2*sin
        x2+512.0
      Next
      y2.f=-CY2
      For i = 0 To bmi2\bmiHeader\biHeight - 1
        tabxy2(i,2)=y2*sin
        tabxy2(i,3)=y2*cos
        y2+512.0
      Next

      i.l=mem2
      w.l=bmi2\bmiHeader\biWidth*4


      maxx.l=bm\bmWidth*4
      maxy.l=mem+(bm\bmWidth-1 + (bm\bmHeight-1) * bm\bmWidth) * 4

      For o.l = 0 To bmi2\bmiHeader\biWidth - 1
        u.l=i
        i+4
        x2cos.f=tabxy2(o,0)
        x2sin.f=tabxy2(o,1)
        For oo.l = 0 To bmi2\bmiHeader\biHeight - 1

          x1b = x2cos - tabxy2(oo,2)
          y1b = x2sin + tabxy2(oo,3)

          x1=x1b/512.0
          y1=y1b/512.0

          If x1b<0 : x1b=-x1b:EndIf
          If y1b<0 : y1b=-y1b:EndIf

          fxl = x1b & $000001FF
          fyl = y1b & $000001FF
          f00l = (511- fxl) * (511-fyl)
          f01l = (511- fxl) * fyl
          f10l = fxl * (511 - fyl)
          f11l = fxl * fyl

          f00l>>9
          f01l>>9
          f10l>>9
          f11l>>9

          If x1 < 0 : PasX.l = -4 : Else : PasX = 4 : EndIf
          If y1 < 0 : PasY.l = -maxx : Else : PasY = maxx : EndIf

          xx1.l=Int(x1)
          xx1*4
          xx2=xx1+PasX
          
          yy1.l=Int(y1)
          yy1*maxx

          pos1.l=mem+xx1 + yy1
          pos2.l=pos1 + PasX
          pos3.l=pos1 + PasY
          pos4.l=pos3 + PasX

          If xx1<0 Or xx1>maxx
            c00=0
            c01=0
          Else                      
            If pos1>=mem And pos1<=maxy 
              c00 = PeekL(pos1)
            Else
              c00=0
            EndIf
            If pos3>=mem And pos3<=maxy 
              c01 = PeekL(pos3)
            Else
              c01=0
            EndIf
          EndIf
          If xx2<0 Or xx2>maxx
            c10=0 
            c11=0
          Else
            If pos2>=mem And pos2<=maxy
              c10 = PeekL(pos2)
            Else
              c10=0
            EndIf
            If pos4>=mem And pos4<=maxy
              c11 = PeekL(pos4)
            Else
              c11=0
            EndIf
          EndIf

          r.l =   (Red(c00) * f00l)>>9 +   (Red(c10) * f10l)>>9 +   (Red(c01) * f01l)>>9 +   (Red(c11) * f11l)>>9
          g.l = (Green(c00) * f00l)>>9 + (Green(c10) * f10l)>>9 + (Green(c01) * f01l)>>9 + (Green(c11) * f11l)>>9
          b.l =  (Blue(c00) * f00l)>>9 +  (Blue(c10) * f10l)>>9 +  (Blue(c01) * f01l)>>9 +  (Blue(c11) * f11l)>>9
       
          PokeL(u , RGB(r, g, b))
          u+w
        Next
      Next
     
      ; On crée la nouvelle image
      NewImageID = CreateImage(#PB_Any, bmi2\bmiHeader\biWidth, bmi2\bmiHeader\biHeight)
      Hdc = CreateCompatibleDC_(GetDC_(ImageID()))
      If Hdc
        SetDIBits_(Hdc, ImageID(), 0, bmi2\bmiHeader\biHeight, Mem2, @bmi2, #DIB_RGB_COLORS) ; on envoie la liste dans l'image
        ReleaseDC_(0, Hdc)
      EndIf
     
      FreeMemory(Mem2)
    EndIf
    FreeMemory(Mem)
  EndIf
 
  ProcedureReturn NewImageID
EndProcedure



;-----------------------------------------
;- Test de rapidité

ImageOrigine = CreateImage(0, 1000, 1000)
StartDrawing(ImageOutput())
  For n = 0 To 999
    For nn = 0 To 999
      Plot(n, nn, Random($FFFFFF))
    Next
  Next
StopDrawing()
Dim Liste(ImageWidth() - 1, ImageHeight() - 1)

#NbTest = 2

Temps1 = ElapsedMilliseconds()

For n = 1 To #NbTest
  ImageModifiee = RotateImageEx2(ImageOrigine, 30)
Next

Temps2 = ElapsedMilliseconds()

Vitesse = (Temps2 - Temps1) / #NbTest
NbPixel = ImageHeight() * ImageWidth()

MessageRequester("Temps", Str(Vitesse) + " ms" + Chr(10) + "Image de " + Str(ImageWidth()) + " * " + Str(ImageHeight()) + " pixels" + Chr(10) + "Nb pixels traités = " + Str(NbPixel), 0)


;-----------------------------------------
;- Test  d'affichage d'image avec rotation
; On dessine une image
ImageNormale = CreateImage(#PB_Any, 80, 100)
StartDrawing(ImageOutput())
  Box(0, 0, 80, 100, $6F6F6F)
  Box(5, 5, 35, 45, $FF)
  Box(40, 5, 35, 45, $FF00)
  Box(5, 50, 35, 45, $FF0000)
  Box(40, 50, 35, 45, $FFFFFF)
StopDrawing()

ImageRotation = RotateImageEx2(UseImage(ImageNormale), 30)

; Création de la fenêtre et de la GadgetList
If OpenWindow(0, 0, 0, 250, 300, #PB_Window_SystemMenu | #PB_Window_ScreenCentered | #PB_Window_MinimizeGadget, "Effect - Rotation d'image") = 0 Or CreateGadgetList(WindowID()) = 0
  End
EndIf

TextGadget(#PB_Any, 10, 10, 100, 15, "Image normale")
ImageGadget(#PB_Any, 10, 25, 0, 0, UseImage(ImageNormale))

TextGadget(#PB_Any, 10, 135, 100, 15, "Rotation de 30")
ImageGadget(#PB_Any, 10, 150, 0, 0, UseImage(ImageRotation))

Repeat
  Event = WaitWindowEvent()
 
Until Event = #PB_EventCloseWindow

End

Publié : mer. 16/févr./2005 11:16
par Le Soldat Inconnu
Bon, ben moi, je suis descendu à 1030 ms au lieu de 1200 sur mon 900mhz

Code : Tout sélectionner

ProcedureDLL.l RotateImageEx2(ImageID, Angle.f) ; Rotation d'une image d'un angle en °
  Protected bmi.BITMAPINFO, bmi2.BITMAPINFO, Hdc.l, NewImageID, Mem, n, nn, bm.BITMAP
  
  Angle = Angle * #Pi / 180 ; On convertit en radian
  
  cos.f = Cos(Angle)
  sin.f = Sin(Angle)
  
  CouleurFond = 0
  
  GetObject_(ImageID, SizeOf(BITMAP), @bm.BITMAP)
  
  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
  
  bmi2\bmiHeader\biSize = SizeOf(BITMAPINFOHEADER)
  bmi2\bmiHeader\biWidth = bm\bmWidth * Abs(cos) + bm\bmHeight * Abs(sin)
  bmi2\bmiHeader\biHeight = bm\bmHeight * Abs(cos) + bm\bmWidth * Abs(sin)
  bmi2\bmiHeader\biPlanes = 1
  bmi2\bmiHeader\biBitCount = 32
  bmi2\bmiHeader\biCompression = #BI_RGB
  
  Mem = AllocateMemory(bm\bmWidth * bm\bmHeight * 4)
  If Mem
    Mem2 = AllocateMemory(bmi2\bmiHeader\biWidth * bmi2\bmiHeader\biHeight * 4)
    If Mem2
      
      Hdc = CreateCompatibleDC_(GetDC_(ImageID))
      If Hdc
        GetDIBits_(Hdc, ImageID, 0, bm\bmHeight, Mem, @bmi, #DIB_RGB_COLORS) ; on envoie la liste dans l'image
        ReleaseDC_(0, Hdc)
      EndIf
      
      CX1 = bm\bmWidth - 1
      CY1 = bm\bmHeight - 1
      CX2 = bmi2\bmiHeader\biWidth - 1
      CY2 = bmi2\bmiHeader\biHeight - 1
      
      For n = 0 To CX2
        x1b.l = (n << 1) - CX2
        Temp1.f = CX1 + x1b * cos
        Temp2.f = CY1 + x1b * sin
        For nn = 0 To CY2
          y1b.l = (nn << 1) - CY2
          
          x1.f = (Temp1 - y1b * sin) / 2
          y1.f = (Temp2 + y1b * cos) / 2
          
          x2.l = x1
          y2.l = y1
          
          fx.f = Abs(x1 - x2)
          fy.f = Abs(y1 - y2)
          f00.f = (1 - fx) * (1 - fy)
          f01.f = (1 - fx) * fy
          f10.f = fx * (1 - fy)
          f11.f = fx * fy
          
          If x1 < x2 : x2b = x2 - 1 : Else : x2b = x2 + 1 : EndIf
          If y1 < y2 : y2b = y2 - 1 : Else : y2b = y2 + 1 : EndIf
          
          If x2 < 0 Or x2 > CX1 
            c00 = 0
            c01 = 0
          Else
            If y2 < 0 Or y2 > CY1
              c00 = 0
            Else
              c00 = PeekL(Mem + (x2 + y2 * bm\bmWidth) * 4)
            EndIf
            If y2b < 0 Or y2b > CY1
              c01 = 0
            Else
              c01 = PeekL(Mem + (x2 + y2b * bm\bmWidth) * 4)
            EndIf
          EndIf
          If x2b < 0 Or x2b > CX1
            c10 = 0
            c11 = 0
          Else
            If y2 < 0 Or y2 > CY1
              c10 = 0
            Else
              c10 = PeekL(Mem + (x2b + y2 * bm\bmWidth) * 4)
            EndIf
            If  y2b < 0 Or y2b > CY1
              c11 = 0
            Else
              c11 = PeekL(Mem + (x2b + y2b * bm\bmWidth) * 4)
            EndIf
          EndIf
          
          r = Red(c00) * f00 + Red(c10) * f10 + Red(c01) * f01 + Red(c11) * f11
          g = Green(c00) * f00 + Green(c10) * f10 + Green(c01) * f01 + Green(c11) * f11
          b = Blue(c00) * f00 + Blue(c10) * f10 + Blue(c01) * f01 + Blue(c11) * f11
          
          PokeL(Mem2 + (n + nn * bmi2\bmiHeader\biWidth) * 4, RGB(r, g, b))
          
        Next
      Next
      
      ; On crée la nouvelle image
      NewImageID = CreateImage(#PB_Any, bmi2\bmiHeader\biWidth, bmi2\bmiHeader\biHeight)
      Hdc = CreateCompatibleDC_(GetDC_(ImageID()))
      If Hdc
        SetDIBits_(Hdc, ImageID(), 0, bmi2\bmiHeader\biHeight, Mem2, @bmi2, #DIB_RGB_COLORS) ; on envoie la liste dans l'image
        ReleaseDC_(0, Hdc)
      EndIf
      
      FreeMemory(Mem2)
    EndIf
    FreeMemory(Mem)
  EndIf
  
  ProcedureReturn NewImageID
EndProcedure


;-----------------------------------------
;- Test de rapidité

ImageOrigine = CreateImage(0, 1000, 1000)
StartDrawing(ImageOutput())
  For n = 0 To 999
    For nn = 0 To 999
      Plot(n, nn, Random($FFFFFF))
    Next
  Next
StopDrawing()
Dim Liste(ImageWidth() - 1, ImageHeight() - 1)

#NbTest = 3

Temps1 = ElapsedMilliseconds()

For n = 1 To #NbTest
  ImageModifiee = RotateImageEx2(ImageOrigine, 30)
Next

Temps2 = ElapsedMilliseconds()

Vitesse = (Temps2 - Temps1) / #NbTest
NbPixel = ImageHeight() * ImageWidth()

MessageRequester("Temps", Str(Vitesse) + " ms" + Chr(10) + "Image de " + Str(ImageWidth()) + " * " + Str(ImageHeight()) + " pixels" + Chr(10) + "Nb pixels traités = " + Str(NbPixel), 0)


;-----------------------------------------
;- Test  d'affichage d'image avec rotation
; On dessine une image
ImageNormale = CreateImage(#PB_Any, 80, 100)
StartDrawing(ImageOutput())
  Box(0, 0, 80, 100, $6F6F6F)
  Box(5, 5, 35, 45, $FF)
  Box(40, 5, 35, 45, $FF00)
  Box(5, 50, 35, 45, $FF0000)
  Box(40, 50, 35, 45, $FFFFFF)
StopDrawing()

ImageRotation = RotateImageEx2(UseImage(ImageNormale), 30)

; Création de la fenêtre et de la GadgetList
If OpenWindow(0, 0, 0, 250, 300, #PB_Window_SystemMenu | #PB_Window_ScreenCentered | #PB_Window_MinimizeGadget, "Effect - Rotation d'image") = 0 Or CreateGadgetList(WindowID()) = 0
  End
EndIf

TextGadget(#PB_Any, 10, 10, 100, 15, "Image normale")
ImageGadget(#PB_Any, 10, 25, 0, 0, UseImage(ImageNormale))

TextGadget(#PB_Any, 10, 135, 100, 15, "Rotation de 30")
ImageGadget(#PB_Any, 10, 150, 0, 0, UseImage(ImageRotation))

Repeat
  Event = WaitWindowEvent()
  
Until Event = #PB_EventCloseWindow

End
Message Edité le 15/02/05 à 12h09

Publié : mer. 16/févr./2005 13:48
par djes
Yo! Bien mais je crois que j'ai un peu plus rapide!

Code : Tout sélectionner

#Pi.f=3.14159265

ProcedureDLL.l RotateImageEx2(ImageID, Angle.f) ; Rotation d'une image d'un angle en °
  Protected bmi.BITMAPINFO, bmi2.BITMAPINFO, Hdc.l, NewImageID, Mem, n, nn, bm.BITMAP, Temp1, Temp2

  DefType.f x1,y1
  DefType.l x1b,y1b,fxl,fyl,f00l,f01l,f10l,f11l

 
  Angle = Angle * #Pi / 180 ; On convertit en radian
 
  GetObject_(ImageID, SizeOf(BITMAP), @bm.BITMAP)
 
  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
 
  bmi2\bmiHeader\biSize = SizeOf(BITMAPINFOHEADER)
  bmi2\bmiHeader\biWidth = Int(bm\bmWidth * Abs(Cos(Angle)) + bm\bmHeight * Abs(Sin(Angle)) + 0.5)
  bmi2\bmiHeader\biHeight = Int(bm\bmHeight * Abs(Cos(Angle)) + bm\bmWidth * Abs(Sin(Angle)) + 0.5)
  bmi2\bmiHeader\biPlanes = 1
  bmi2\bmiHeader\biBitCount = 32
  bmi2\bmiHeader\biCompression = #BI_RGB
 
  Mem = AllocateMemory(bm\bmWidth * bm\bmHeight * 4)
  If Mem
    Mem2 = AllocateMemory(bmi2\bmiHeader\biWidth * bmi2\bmiHeader\biHeight * 4)
    If Mem2
     
      Hdc = CreateCompatibleDC_(GetDC_(ImageID))
      If Hdc
        GetDIBits_(Hdc, ImageID, 0, bm\bmHeight, Mem, @bmi, #DIB_RGB_COLORS) ; on envoie la liste dans l'image
        ReleaseDC_(0, Hdc)
      EndIf
     
      CX1 = (bm\bmWidth - 1) * 512 / 2
      CY1 = (bm\bmHeight - 1) * 512 / 2
      CX2 = (bmi2\bmiHeader\biWidth - 1) * 512 / 2
      CY2 = (bmi2\bmiHeader\biHeight - 1) * 512 / 2
     
      ;un seul Dim est surement plus rapide que 2
      If bmi2\bmiHeader\biWidth>bmi2\bmiHeader\biHeight
        Dim tabxy2.l(bmi2\bmiHeader\biWidth,4)
      Else
        Dim tabxy2.l(bmi2\bmiHeader\biHeight,4)
      EndIf
      x2.f=-CX2

      sin.f=Sin(angle)
      cos.f=Cos(angle)
      For i = 0 To bmi2\bmiHeader\biWidth - 1
        tabxy2(i,0)=CX1+x2*cos
        tabxy2(i,1)=CY1+x2*sin
        x2+512.0
      Next
      y2.f=-CY2
      For i = 0 To bmi2\bmiHeader\biHeight - 1
        tabxy2(i,2)=y2*sin
        tabxy2(i,3)=y2*cos
        y2+512.0
      Next

      i.l=mem2
      w.l=bmi2\bmiHeader\biWidth*4

      tailleligne=bm\bmWidth * 4
      maxx.l=(bm\bmWidth-1)*4
      maxy.l=(bm\bmHeight-1) * tailleligne

      For o.l = 0 To bmi2\bmiHeader\biWidth - 1
        u.l=i
        i+4
        x2cos.l=tabxy2(o,0)
        x2sin.l=tabxy2(o,1)
        For oo.l = 0 To bmi2\bmiHeader\biHeight - 1

          x1b = x2cos - tabxy2(oo,2)
          y1b = x2sin + tabxy2(oo,3)

;          If xx1<0 : xx1=-xx1:EndIf
          If yy1<0 : yy1=-yy1:EndIf ;!!!!!!!!!
         
          If xx1 < 0 : PasX.l = -4 : Else : PasX = 4 : EndIf
          If yy1 < 0 : PasY.l = -tailleligne: Else : PasY = tailleligne: EndIf

          xx1.l=x1b>>9
          xx1*4  
          yy1.l=y1b>>9
          yy1*tailleligne
          xx2=xx1+PasX
          yy2=yy1+PasY

          fxl = x1b & $000001FF
          fyl = y1b & $000001FF
          f00l = (511- fxl) * (511-fyl)
          f01l = (511- fxl) * fyl
          f10l = fxl * (511 - fyl)
          f11l = fxl * fyl

          f00l>>9
          f01l>>9
          f10l>>9
          f11l>>9

          If xx1<0 Or xx1>maxx
            c00=0
            c01=0
          Else                     
            pos1.l=mem+xx1 + yy1
            If yy1<0 Or yy1>maxy
              c00 = 0 
            Else
              c00 =PeekL(pos1)
            EndIf
            If yy2<0 Or yy2>maxy
              c01 = 0
            Else
              c01 = PeekL(pos1+PasY)
            EndIf
          EndIf
          If xx2<0 Or xx2>maxx
            c10=0
            c11=0
          Else
            pos1.l=mem+xx2 + yy1
            If yy1<0 Or yy1>maxy
              c10 = 0
            Else
              c10 = PeekL(pos1)
            EndIf
            If yy2<0 Or yy2>maxy
              c11 = 0
            Else
              c11 = PeekL(pos1+PasY)
            EndIf
          EndIf

          r.l =   (Red(c00) * f00l)>>9 +   (Red(c10) * f10l)>>9 +   (Red(c01) * f01l)>>9 +   (Red(c11) * f11l)>>9
          g.l = (Green(c00) * f00l)>>9 + (Green(c10) * f10l)>>9 + (Green(c01) * f01l)>>9 + (Green(c11) * f11l)>>9
          b.l =  (Blue(c00) * f00l)>>9 +  (Blue(c10) * f10l)>>9 +  (Blue(c01) * f01l)>>9 +  (Blue(c11) * f11l)>>9
       
          PokeL(u , RGB(r, g, b))
          u+w
        Next
      Next
     
      ; On crée la nouvelle image
      NewImageID = CreateImage(#PB_Any, bmi2\bmiHeader\biWidth, bmi2\bmiHeader\biHeight)
      Hdc = CreateCompatibleDC_(GetDC_(ImageID()))
      If Hdc
        SetDIBits_(Hdc, ImageID(), 0, bmi2\bmiHeader\biHeight, Mem2, @bmi2, #DIB_RGB_COLORS) ; on envoie la liste dans l'image
        ReleaseDC_(0, Hdc)
      EndIf
     
      FreeMemory(Mem2)
    EndIf
    FreeMemory(Mem)
  EndIf
 
  ProcedureReturn NewImageID
EndProcedure



;-----------------------------------------
;- Test de rapidité

ImageOrigine = CreateImage(0, 1000, 1000)
StartDrawing(ImageOutput())
  For n = 0 To 999
    For nn = 0 To 999
      Plot(n, nn, Random($FFFFFF))
    Next
  Next
StopDrawing()
Dim Liste(ImageWidth() - 1, ImageHeight() - 1)

#NbTest = 2

Temps1 = ElapsedMilliseconds()

For n = 1 To #NbTest
  ImageModifiee = RotateImageEx2(ImageOrigine, 30)
Next

Temps2 = ElapsedMilliseconds()

Vitesse = (Temps2 - Temps1) / #NbTest
NbPixel = ImageHeight() * ImageWidth()

MessageRequester("Temps", Str(Vitesse) + " ms" + Chr(10) + "Image de " + Str(ImageWidth()) + " * " + Str(ImageHeight()) + " pixels" + Chr(10) + "Nb pixels traités = " + Str(NbPixel), 0)


;-----------------------------------------
;- Test  d'affichage d'image avec rotation
; On dessine une image
ImageNormale = CreateImage(#PB_Any, 80, 100)
StartDrawing(ImageOutput())
  Box(0, 0, 80, 100, $6F6F6F)
  Box(5, 5, 35, 45, $FF)
  Box(40, 5, 35, 45, $FF00)
  Box(5, 50, 35, 45, $FF0000)
  Box(40, 50, 35, 45, $FFFFFF)
StopDrawing()

ImageRotation = RotateImageEx2(UseImage(ImageNormale), 30)

; Création de la fenêtre et de la GadgetList
If OpenWindow(0, 0, 0, 250, 300, #PB_Window_SystemMenu | #PB_Window_ScreenCentered | #PB_Window_MinimizeGadget, "Effect - Rotation d'image") = 0 Or CreateGadgetList(WindowID()) = 0
  End
EndIf

TextGadget(#PB_Any, 10, 10, 100, 15, "Image normale")
ImageGadget(#PB_Any, 10, 25, 0, 0, UseImage(ImageNormale))

TextGadget(#PB_Any, 10, 135, 100, 15, "Rotation de 30")
ImageGadget(#PB_Any, 10, 150, 0, 0, UseImage(ImageRotation))

Repeat
  Event = WaitWindowEvent()
 
Until Event = #PB_EventCloseWindow

End
:D

Publié : mer. 16/févr./2005 13:58
par Le Soldat Inconnu
900 ms 8O :D cool, je regarde ça en détail

Publié : mer. 16/févr./2005 18:49
par djes
Bon voilà un peu d'asm. On peut faire mieux, mais je fais une pause ;)

Code : Tout sélectionner

#Pi.f=3.14159265

ProcedureDLL.l RotateImageEx2(ImageID, Angle.f) ; Rotation d'une image d'un angle en °
  Protected bmi.BITMAPINFO, bmi2.BITMAPINFO, Hdc.l, NewImageID, Mem, n, nn, bm.BITMAP, Temp1, Temp2

  DefType.f x1,y1
  DefType.l x1b,y1b,fxl,fyl,f00l,f01l,f10l,f11l

 
  Angle = Angle * #Pi / 180 ; On convertit en radian
 
  GetObject_(ImageID, SizeOf(BITMAP), @bm.BITMAP)
 
  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
 
  bmi2\bmiHeader\biSize = SizeOf(BITMAPINFOHEADER)
  bmi2\bmiHeader\biWidth = Int(bm\bmWidth * Abs(Cos(Angle)) + bm\bmHeight * Abs(Sin(Angle)) + 0.5)
  bmi2\bmiHeader\biHeight = Int(bm\bmHeight * Abs(Cos(Angle)) + bm\bmWidth * Abs(Sin(Angle)) + 0.5)
  bmi2\bmiHeader\biPlanes = 1
  bmi2\bmiHeader\biBitCount = 32
  bmi2\bmiHeader\biCompression = #BI_RGB
 
  Mem = AllocateMemory(bm\bmWidth * bm\bmHeight * 4)
  If Mem
    Mem2 = AllocateMemory(bmi2\bmiHeader\biWidth * bmi2\bmiHeader\biHeight * 4)
    If Mem2
     
      Hdc = CreateCompatibleDC_(GetDC_(ImageID))
      If Hdc
        GetDIBits_(Hdc, ImageID, 0, bm\bmHeight, Mem, @bmi, #DIB_RGB_COLORS) ; on envoie la liste dans l'image
        ReleaseDC_(0, Hdc)
      EndIf
     
      CX1 = (bm\bmWidth - 1) * 512 / 2
      CY1 = (bm\bmHeight - 1) * 512 / 2
      CX2 = (bmi2\bmiHeader\biWidth - 1) * 512 / 2
      CY2 = (bmi2\bmiHeader\biHeight - 1) * 512 / 2
     
      ;un seul Dim est surement plus rapide que 2
      If bmi2\bmiHeader\biWidth>bmi2\bmiHeader\biHeight
        Dim tabxy2.l(bmi2\bmiHeader\biWidth,4)
      Else
        Dim tabxy2.l(bmi2\bmiHeader\biHeight,4)
      EndIf
      x2.f=-CX2

      sin.f=Sin(angle)
      cos.f=Cos(angle)
      For i = 0 To bmi2\bmiHeader\biWidth - 1
        tabxy2(i,0)=CX1+x2*cos
        tabxy2(i,1)=CY1+x2*sin
        x2+512.0
      Next
      y2.f=-CY2
      For i = 0 To bmi2\bmiHeader\biHeight - 1
        tabxy2(i,2)=y2*sin
        tabxy2(i,3)=y2*cos
        y2+512.0
      Next

      i.l=mem2
      w.l=bmi2\bmiHeader\biWidth*4

      tailleligne=bm\bmWidth * 4
      maxx.l=(bm\bmWidth-1)*4
      maxy.l=(bm\bmHeight-1) * tailleligne

      For o.l = 0 To bmi2\bmiHeader\biWidth - 1
        u.l=i
        i+4
        x2cos.l=tabxy2(o,0)
        x2sin.l=tabxy2(o,1)
        For oo.l = 0 To bmi2\bmiHeader\biHeight - 1

          x1b = x2cos - tabxy2(oo,2)
          y1b = x2sin + tabxy2(oo,3)

;          If xx1<0 : xx1=-xx1:EndIf
          If yy1<0 : yy1=-yy1:EndIf ;!!!!!!!!!
         
          If xx1 < 0 : PasX.l = -4 : Else : PasX = 4 : EndIf
          If yy1 < 0 : PasY.l = -tailleligne: Else : PasY = tailleligne: EndIf

          xx1.l=x1b>>9
          xx1*4  
          yy1.l=y1b>>9
          yy1*tailleligne
          xx2=xx1+PasX
          yy2=yy1+PasY

          fxl = x1b & $000001FF
          fyl = y1b & $000001FF
          f00l = (511- fxl) * (511-fyl)
          f01l = (511- fxl) * fyl
          f10l = fxl * (511 - fyl)
          f11l = fxl * fyl

          f00l>>9
          f01l>>9
          f10l>>9
          f11l>>9

          If xx1<0 Or xx1>maxx
            c00=0
            c01=0
          Else                     
            pos1.l=mem+xx1 + yy1
            If yy1<0 Or yy1>maxy
              c00 = 0 
            Else
              MOV eax,pos1
              MOV eax,[eax]
              MOV c00,eax
              ;c00 =PeekL(pos1)
            EndIf
            If yy2<0 Or yy2>maxy
              c01 = 0
            Else
              MOV eax,pos1
              ADD eax,PasY
              MOV eax,[eax]
              MOV c01,eax
              ;c01 = PeekL(pos1+PasY)
            EndIf
          EndIf
          If xx2<0 Or xx2>maxx
            c10=0
            c11=0
          Else
            pos1.l=mem+xx2 + yy1
            If yy1<0 Or yy1>maxy
              c10 = 0
            Else
              MOV eax,pos1
              MOV eax,[eax]
              MOV c10,eax
              ;c10 = PeekL(pos1)
            EndIf
            If yy2<0 Or yy2>maxy
              c11 = 0
            Else
              MOV eax,pos1
              ADD eax,PasY
              MOV eax,[eax]
              MOV c11,eax
              ;c11 = PeekL(pos1+PasY)
            EndIf
          EndIf

;          r.l =   (Red(c00) * f00l)>>9 +   (Red(c10) * f10l)>>9 +   (Red(c01) * f01l)>>9 +   (Red(c11) * f11l)>>9
;(Red(c00) * f00l)>>9
  MOV eax,c00
  AND eax,$FF
  IMUL eax,f00l

;(Red(c10) * f10l)>>9
  MOV ebx,c10
  AND ebx,$FF
  IMUL ebx,f10l
  ADD eax,ebx
  
;(Red(c01) * f01l)>>9
  MOV ebx,c01
  AND ebx,$FF
  IMUL ebx,f01l
  ADD eax,ebx
  
;(Red(c11) * f11l)>>9  
  MOV ebx,c11
  AND ebx,$FF
  IMUL ebx,f11l
  ADD eax,ebx
  
  SAR eax,9
  AND eax,$000000FF
  MOV ecx,eax

;          g.l = (Green(c00) * f00l)>>9 + (Green(c10) * f10l)>>9 + (Green(c01) * f01l)>>9 + (Green(c11) * f11l)>>9
;(Green(c00) * f00l)>>9
  MOV eax,c00
  AND eax,$00FF00
  IMUL eax,f00l

;(Green(c10) * f10l)>>9
  MOV ebx,c10
  AND ebx,$00FF00
  IMUL ebx,f10l
  ADD eax,ebx

;(Green(c01) * f01l)>>9
  MOV ebx,c01
  AND ebx,$00FF00
  IMUL ebx,f01l
  ADD eax,ebx

;(Green(c11) * f11l)>>9
  MOV ebx,c11
  AND ebx,$00FF00
  IMUL ebx,f11l
  ADD eax,ebx

  SAR eax,9
  AND eax,$0000FF00
  OR ecx,eax

;          b.l =  (Blue(c00) * f00l)>>9 +  (Blue(c10) * f10l)>>9 +  (Blue(c01) * f01l)>>9 +  (Blue(c11) * f11l)>>9
;ici les opérations font déborder le registre, aussi je décale tout de 8 vers la gauche pour garder un peu de marge
;(Blue(c00) * f00l)>>9
  MOV eax,c00
  BSWAP eax
  AND eax,$FF00
  IMUL eax,f00l

;(Blue(c10) * f10l)>>9 
  MOV ebx,c10
  BSWAP ebx
  AND ebx,$FF00
  IMUL ebx,f10l
  ADD eax,ebx
  
;(Blue(c01) * f01l)>>9
  MOV ebx,c01
  BSWAP ebx
  AND ebx,$FF00
  IMUL ebx,f01l
  ADD eax,ebx

;(Blue(c11) * f11l)>>9
  MOV ebx,c11
  BSWAP ebx
  AND ebx,$FF00
  IMUL ebx,f11l
  ADD eax,ebx
  SAR eax,9

  BSWAP eax 

  AND eax,$00FF0000
  OR ecx,eax

          ;PokeL(u , r|g|b)
  MOV eax,u
  MOV [eax],ecx       

          u+w
        Next
      Next
     
      ; On crée la nouvelle image
      NewImageID = CreateImage(#PB_Any, bmi2\bmiHeader\biWidth, bmi2\bmiHeader\biHeight)
      Hdc = CreateCompatibleDC_(GetDC_(ImageID()))
      If Hdc
        SetDIBits_(Hdc, ImageID(), 0, bmi2\bmiHeader\biHeight, Mem2, @bmi2, #DIB_RGB_COLORS) ; on envoie la liste dans l'image
        ReleaseDC_(0, Hdc)
      EndIf
     
      FreeMemory(Mem2)
    EndIf
    FreeMemory(Mem)
  EndIf
 
  ProcedureReturn NewImageID
EndProcedure



;-----------------------------------------
;- Test de rapidité

ImageOrigine = CreateImage(0, 1000, 1000)
StartDrawing(ImageOutput())
  For n = 0 To 999
    For nn = 0 To 999
      Plot(n, nn, Random($FFFFFF))
    Next
  Next
StopDrawing()
Dim Liste(ImageWidth() - 1, ImageHeight() - 1)

#NbTest = 2

Temps1 = ElapsedMilliseconds()

For n = 1 To #NbTest
  ImageModifiee = RotateImageEx2(ImageOrigine, 30)
Next

Temps2 = ElapsedMilliseconds()

Vitesse = (Temps2 - Temps1) / #NbTest
NbPixel = ImageHeight() * ImageWidth()

MessageRequester("Temps", Str(Vitesse) + " ms" + Chr(10) + "Image de " + Str(ImageWidth()) + " * " + Str(ImageHeight()) + " pixels" + Chr(10) + "Nb pixels traités = " + Str(NbPixel), 0)


;-----------------------------------------
;- Test  d'affichage d'image avec rotation
; On dessine une image
ImageNormale = CreateImage(#PB_Any, 80, 100)
StartDrawing(ImageOutput())
  Box(0, 0, 80, 100, $6F6F6F)
  Box(5, 5, 35, 45, $FF)
  Box(40, 5, 35, 45, $FF00)
  Box(5, 50, 35, 45, $FF0000)
  Box(40, 50, 35, 45, $FFFFFF)
StopDrawing()

ImageRotation = RotateImageEx2(UseImage(ImageNormale), 30)

; Création de la fenêtre et de la GadgetList
If OpenWindow(0, 0, 0, 250, 300, #PB_Window_SystemMenu | #PB_Window_ScreenCentered | #PB_Window_MinimizeGadget, "Effect - Rotation d'image") = 0 Or CreateGadgetList(WindowID()) = 0
  End
EndIf

TextGadget(#PB_Any, 10, 10, 100, 15, "Image normale")
ImageGadget(#PB_Any, 10, 25, 0, 0, UseImage(ImageNormale))

TextGadget(#PB_Any, 10, 135, 100, 15, "Rotation de 30")
ImageGadget(#PB_Any, 10, 150, 0, 0, UseImage(ImageRotation))

Repeat
  Event = WaitWindowEvent()
 
Until Event = #PB_EventCloseWindow

End

Publié : mer. 16/févr./2005 21:28
par Le Soldat Inconnu
c'est plus lent chez moi, ton dernier code 940 ms :roll: comme quoi PB est optimiser au niveau asm

Publié : mer. 16/févr./2005 21:36
par comtois
le dernier code de djes 257 ms
l'avant dernier de djes 304 ms
le dernier code du soldat 396 ms

c'est intéressant ces codes .Bravo.

Publié : mer. 16/févr./2005 22:39
par djes
Le Soldat Inconnu a écrit :c'est plus lent chez moi, ton dernier code 940 ms :roll: comme quoi PB est optimiser au niveau asm
Comme je le disais c'est surtout un problème d'alignement du code, et peut-être aussi du type de processeur. Tu as de l'intel ou de l'amd?

Publié : mer. 16/févr./2005 22:47
par Le Soldat Inconnu
AMD

bon, de toute façon, j'ai 800ms sur mon 900mhz :D

Sachant que 225 ms sont fixes dû a l'API utilisé pour récupèrer et envoyer l'image. la marge de progression se réduit

Je suis parti de 4.5 secondes :roll: j'aurai jamais pensé pouvoir atteindre ce stade. plus de 5 fois plus rapide :)

Code : Tout sélectionner

ProcedureDLL.l RotateImageEx2(ImageID, Angle.f) ; Rotation d'une image d'un angle en °
  Protected bmi.BITMAPINFO, bmi2.BITMAPINFO, Hdc.l, NewImageID, Mem, n, nn, bm.BITMAP
  
  Angle = Angle * #Pi / 180 ; On convertit en radian
  
  Cos.f = Cos(Angle)
  Sin.f = Sin(Angle)
  
  CouleurFond = 0
  
  GetObject_(ImageID, SizeOf(BITMAP), @bm.BITMAP)
  
  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
  
  bmi2\bmiHeader\biSize = SizeOf(BITMAPINFOHEADER)
  bmi2\bmiHeader\biWidth = bm\bmWidth * Abs(Cos) + bm\bmHeight * Abs(Sin)
  bmi2\bmiHeader\biHeight = bm\bmHeight * Abs(Cos) + bm\bmWidth * Abs(Sin)
  bmi2\bmiHeader\biPlanes = 1
  bmi2\bmiHeader\biBitCount = 32
  bmi2\bmiHeader\biCompression = #BI_RGB
  
  Mem = AllocateMemory(bm\bmWidth * bm\bmHeight * 4)
  If Mem
    Mem2 = AllocateMemory(bmi2\bmiHeader\biWidth * bmi2\bmiHeader\biHeight * 4)
    If Mem2
      
      Hdc = CreateCompatibleDC_(GetDC_(ImageID))
      If Hdc
        GetDIBits_(Hdc, ImageID, 0, bm\bmHeight, Mem, @bmi, #DIB_RGB_COLORS) ; on envoie la liste dans l'image
        ReleaseDC_(0, Hdc)
      EndIf
      
      CX1 = bm\bmWidth - 1
      CY1 = bm\bmHeight - 1
      CX2 = bmi2\bmiHeader\biWidth - 1
      CY2 = bmi2\bmiHeader\biHeight - 1
      
      Mem01 = Mem + bm\bmWidth * 4
      Mem10 = Mem + 4
      Mem11 = Mem01 + 4
      
      For n = 0 To CX2
        x1b.l = n * 2 - CX2
        Temp1.f = CX1 + x1b * Cos
        Temp2.f = CY1 + x1b * Sin
        For nn = 0 To CY2
          y1b.l = nn * 2 - CY2
          
          x1.f = (Temp1 - y1b * Sin) / 2
          y1.f = (Temp2 + y1b * Cos) / 2
          
          x2.l = x1
          y2.l = y1
          
          If x1 < x2
            DEC x2
          EndIf
          If y1 < y2
            DEC y2
          EndIf
          
          x2b = x2 + 1
          y2b = y2 + 1
          
          If x2b >= 0 And x2 <= CX1 And y2b >= 0 And y2 <= CY1 ; On filtre si on est completement en dehors de l'image
          
            fx.f = x1 - x2
            fy.f = y1 - y2
            f00.f = (1 - fx) * (1 - fy)
            f01.f = (1 - fx) * fy
            f10.f = fx * (1 - fy)
            f11.f = fx * fy
            
            MemTemp = (x2 + y2 * bm\bmWidth) * 4
            
            If x2 >= 0 And x2 <= CX1
              If y2 >= 0 And y2 <= CY1
                c00 = PeekL(Mem + MemTemp)
              Else
                c00 = 0
              EndIf
              If y2b >= 0 And y2b <= CY1
                c01 = PeekL(Mem01 + MemTemp)
              Else
                c01 = 0
              EndIf
            Else
              c00 = 0
              c01 = 0
            EndIf
            If x2b >= 0 And x2b <= CX1
              If y2 >= 0 And y2 <= CY1
                c10 = PeekL(Mem10 + MemTemp)
              Else
                c10 = 0
              EndIf
              If  y2b >= 0 And y2b <= CY1
                c11 = PeekL(Mem11 + MemTemp)
              Else
                c11 = 0
              EndIf
            Else
              c10 = 0
              c11 = 0
            EndIf
            
            r = Red(c00) * f00 + Red(c10) * f10 + Red(c01) * f01 + Red(c11) * f11
            g = Green(c00) * f00 + Green(c10) * f10 + Green(c01) * f01 + Green(c11) * f11
            b = Blue(c00) * f00 + Blue(c10) * f10 + Blue(c01) * f01 + Blue(c11) * f11
            
            PokeL(Mem2 + (n + nn * bmi2\bmiHeader\biWidth) * 4, RGB(r, g, b))
          
          Else
            PokeL(Mem2 + (n + nn * bmi2\bmiHeader\biWidth) * 4, 0)
          EndIf
          
        Next
      Next
      
      ; On crée la nouvelle image
      NewImageID = CreateImage(#PB_Any, bmi2\bmiHeader\biWidth, bmi2\bmiHeader\biHeight)
      Hdc = CreateCompatibleDC_(GetDC_(ImageID()))
      If Hdc
        SetDIBits_(Hdc, ImageID(), 0, bmi2\bmiHeader\biHeight, Mem2, @bmi2, #DIB_RGB_COLORS) ; on envoie la liste dans l'image
        ReleaseDC_(0, Hdc)
      EndIf
      
      FreeMemory(Mem2)
    EndIf
    FreeMemory(Mem)
  EndIf
  
  ProcedureReturn NewImageID
EndProcedure


;-----------------------------------------
;- Test de rapidité

ImageOrigine = CreateImage(0, 1000, 1000)
StartDrawing(ImageOutput())
  For n = 0 To 999
    For nn = 0 To 999
      Plot(n, nn, Random($FFFFFF))
    Next
  Next
StopDrawing()
Dim Liste(ImageWidth() - 1, ImageHeight() - 1)

#NbTest = 4

Temps1 = ElapsedMilliseconds()

For n = 1 To #NbTest
  ImageModifiee = RotateImageEx2(ImageOrigine, 30)
Next

Temps2 = ElapsedMilliseconds()

Vitesse = (Temps2 - Temps1) / #NbTest
NbPixel = ImageHeight() * ImageWidth()

MessageRequester("Temps", Str(Vitesse) + " ms" + Chr(10) + "Image de " + Str(ImageWidth()) + " * " + Str(ImageHeight()) + " pixels" + Chr(10) + "Nb pixels traités = " + Str(NbPixel), 0)


;-----------------------------------------
;- Test  d'affichage d'image avec rotation
; On dessine une image
ImageNormale = CreateImage(#PB_Any, 80, 100)
StartDrawing(ImageOutput())
  Box(0, 0, 80, 100, $6F6F6F)
  Box(5, 5, 35, 45, $FF)
  Box(40, 5, 35, 45, $FF00)
  Box(5, 50, 35, 45, $FF0000)
  Box(40, 50, 35, 45, $FFFFFF)
StopDrawing()

ImageRotation = RotateImageEx2(UseImage(ImageNormale), 30)

; Création de la fenêtre et de la GadgetList
If OpenWindow(0, 0, 0, 250, 300, #PB_Window_SystemMenu | #PB_Window_ScreenCentered | #PB_Window_MinimizeGadget, "Effect - Rotation d'image") = 0 Or CreateGadgetList(WindowID()) = 0
  End
EndIf

TextGadget(#PB_Any, 10, 10, 100, 15, "Image normale")
ImageGadget(#PB_Any, 10, 25, 0, 0, UseImage(ImageNormale))

TextGadget(#PB_Any, 10, 135, 100, 15, "Rotation de 30")
ImageGadget(#PB_Any, 10, 150, 0, 0, UseImage(ImageRotation))

Repeat
  Event = WaitWindowEvent()
  
Until Event = #PB_EventCloseWindow

End