Page 6 sur 8

Publié : dim. 20/févr./2005 20:53
par Le Soldat Inconnu
Flype, j'ai la fonction avec couleur de fond dans la lib et il n'y a aucune différence de vitesse :wink:
Le filtrage est toujours la, sauf qu'on écrit une valeur au lieu de 0.

Djes : j'avais pas vu cette modif :wink: c'est bon

Publié : lun. 21/févr./2005 0:05
par Fred
Je viens juste de tester le code de Flype et ca rotate pas terrible, c'est normal ?

Publié : lun. 21/févr./2005 10:09
par djes
Soldat> :)

Fred> Qu'est-ce que tu veux dire par là? Ici la routine marche plutôt bien... C'est par rapport au test de Flype?

Publié : lun. 21/févr./2005 11:44
par Le Soldat Inconnu
Je n'ai pas essayer le code de Flype, je l'ai simplement survolé

En regardant de plus près, voici les erreurs de flype :
- Un redimmensionnement qui ne sert à rien après la rotation de l'image
- Il faut inverser les composantes RGB de la couleur de fond
- Une mauvaise modification du code pour insérer la couleur de fond ce qui le ralentit fortement.


Si on veut que le centre de l'image soit toujours au même endroit, il faut déplacer l'imagegadget en fonction de l'angle


Sinon, la qualité du lissage est nickel (la même que photoshop) et c'est presque aussi rapide que photoshop.

La dernière version de la lib va également légèrement plus vite que la lib "Rotation" donnée par Flype vers le début du sujet alors que celle-ci n'a pas de lissage :D

Code : Tout sélectionner

ProcedureDLL.l RotateImageEx2(ImageID, Angle.f, CouleurFond) ; 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 = RGB(Blue(CouleurFond), Green(CouleurFond), Red(CouleurFond))
  
  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 
      CX1b = CX1 * 0.5
      CY1b = CY1 * 0.5
      CX2b = CX2 * 0.5
      CY2b = CY2 * 0.5
       
      Mem01 = Mem + bm\bmWidth * 4
      Mem10 = Mem + 4
      Mem11 = Mem01 + 4
      
      Mem2Temp = Mem2
      
      For nn = 0 To CY2 
        y1b.f = nn - CY2b
        Temp1.f = CX1b - y1b * Sin
        Temp2.f = CY1b + y1b * Cos
        For n = 0 To CX2
          x1b.f = n - CX2b
          
          x1.f = Temp1 + x1b * Cos
          y1.f = Temp2 + x1b * Sin 
          
          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 
            f10.f = 1 - fy 
            f01.f = f00 * fy 
            f00 * f10 
            f10 * fx 
            f11.f = fx * fy 
          
            MemTemp = (x2 + y2 * bm\bmWidth) * 4 
            DefType.l c00, c01, c11, c10 
            
            If x2 >= 0 And x2 <= CX1 
              If y2 >= 0 And y2 <= CY1 
                MOV Eax,Mem 
                ADD Eax,MemTemp 
                MOV Eax,[Eax] 
                MOV c00,Eax 
                ;c00 = PeekL(Mem + MemTemp) 
              Else 
                c00 = CouleurFond
              EndIf 
              If y2b >= 0 And y2b <= CY1 
                MOV Eax,Mem01 
                ADD Eax,MemTemp 
                MOV Eax,[Eax] 
                MOV c01,Eax 
                ;c01 = PeekL(Mem01 + MemTemp) 
              Else 
                c01 = CouleurFond
              EndIf 
            Else 
              c00 = CouleurFond
              c01 = CouleurFond
            EndIf 
            If x2b >= 0 And x2b <= CX1 
              If y2 >= 0 And y2 <= CY1 
                MOV Eax,Mem10 
                ADD Eax,MemTemp 
                MOV Eax,[Eax] 
                MOV c10,Eax 
                ;c10 = PeekL(Mem10 + MemTemp) 
              Else 
                c10 = CouleurFond
              EndIf 
              If  y2b >= 0 And y2b <= CY1 
                MOV Eax,Mem11 
                ADD Eax,MemTemp 
                MOV Eax,[Eax] 
                MOV c11,Eax 
                ;c11 = PeekL(Mem11 + MemTemp) 
              Else 
                c11 = CouleurFond
              EndIf 
            Else 
              c10 = CouleurFond
              c11 = CouleurFond
            EndIf 
    
            DefType.l r1,r2,r3,r4 , g1,g2,g3,g4 , b1,b2,b3,b4 

            MOV Eax,c00 
            MOV Ebx,Eax 
            MOV Ecx,Eax 

            And Eax,$FF 
            MOV r1,Eax 
            And Ebx,$FF00 
            MOV g1,Ebx 
            And Ecx,$FF0000 
            MOV b1,Ecx 

            MOV Eax,c10 
            MOV Ebx,Eax 
            MOV Ecx,Eax 

            And Eax,$FF 
            MOV r2,Eax 
            And Ebx,$FF00 
            MOV g2,Ebx 
            And Ecx,$FF0000 
            MOV b2,Ecx 

            MOV Eax,c01 
            MOV Ebx,Eax 
            MOV Ecx,Eax 

            And Eax,$FF 
            MOV r3,Eax 
            And Ebx,$FF00 
            MOV g3,Ebx 
            And Ecx,$FF0000 
            MOV b3,Ecx 

            MOV Eax,c11 
            MOV Ebx,Eax 
            MOV Ecx,Eax 

            And Eax,$FF 
            MOV r4,Eax 
            And Ebx,$FF00 
            MOV g4,Ebx 
            And Ecx,$FF0000 
            MOV b4,Ecx 
      
            r = r1 * f00 + r2 * f10 + r3 * f01 + r4 * f11   ;pure fait très bien tout ça 
            g = g1 * f00 + g2 * f10 + g3 * f01 + g4 * f11 
            b = b1 * f00 + b2 * f10 + b3 * f01 + b4 * f11 
          
            MOV Eax,r 
            MOV Ebx,g 
            MOV Ecx,b 
            And Eax,$FF                                      ;toute l'astuce consiste à laisser les triplets à leur place et à les multiplier là. On évite ainsi les décalages 
            And Ebx,$FF00 
            And Ecx,$FF0000 
            Or Eax,Ebx 
            Or Eax,Ecx 

            MOV Ebx,Mem2Temp 
            MOV [Ebx],Eax 
          
          Else 

            MOV Ebx,Mem2Temp 
            MOV Eax,CouleurFond 
            MOV [Ebx],Eax 

          EndIf 
          
          Mem2Temp + 4 
          
        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, 0)
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()

CouleurFondFenetre = GetSysColor_(#COLOR_3DFACE) ; Couleur de fond des fenêtres de Windows
ImageRotation = RotateImageEx2(UseImage(ImageNormale), 30, CouleurFondFenetre)

; 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))

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

SetTimer_(WindowID(), 0, 25, 0)
Angle = 30
Repeat
  Event = WaitWindowEvent()
  
  If Event = #WM_TIMER
    Angle + 1
    If Angle = 360
      Angle = 0
    EndIf
    FreeImage(ImageRotation)
    ImageRotation = RotateImageEx(UseImage(ImageNormale), Angle, CouleurFondFenetre)
    SetGadgetState(Rotation, UseImage(ImageRotation))
    SetGadgetText(RotationTexte, "Rotation de " + Str(Angle) + "°")
  EndIf
  
Until Event = #PB_EventCloseWindow

KillTimer_(WindowID(), 0)

End

Publié : lun. 21/févr./2005 12:05
par nico
L'image vascille, cela ne le faisait pas avec le code de Flype.

Publié : lun. 21/févr./2005 12:11
par Le Soldat Inconnu
Fred > je pense que tu t'attendais à ceci :

Code : Tout sélectionner

ProcedureDLL.l RotateImageEx2(ImageID, Angle.f, CouleurFond) ; 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 = RGB(Blue(CouleurFond), Green(CouleurFond), Red(CouleurFond))
  
  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 
      CX1b = CX1 * 0.5
      CY1b = CY1 * 0.5
      CX2b = CX2 * 0.5
      CY2b = CY2 * 0.5
       
      Mem01 = Mem + bm\bmWidth * 4
      Mem10 = Mem + 4
      Mem11 = Mem01 + 4
      
      Mem2Temp = Mem2
      
      For nn = 0 To CY2 
        y1b.f = nn - CY2b
        Temp1.f = CX1b - y1b * Sin
        Temp2.f = CY1b + y1b * Cos
        For n = 0 To CX2
          x1b.f = n - CX2b
          
          x1.f = Temp1 + x1b * Cos
          y1.f = Temp2 + x1b * Sin
          
          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 
            f10.f = 1 - fy 
            f01.f = f00 * fy 
            f00 * f10 
            f10 * fx 
            f11.f = fx * fy 
          
            MemTemp = (x2 + y2 * bm\bmWidth) * 4 
            DefType.l c00, c01, c11, c10 
            
            If x2 >= 0 And x2 <= CX1 
              If y2 >= 0 And y2 <= CY1 
                MOV eax,Mem 
                ADD eax,MemTemp 
                MOV eax,[eax] 
                MOV c00,eax 
                ;c00 = PeekL(Mem + MemTemp) 
              Else 
                c00 = CouleurFond
              EndIf 
              If y2b >= 0 And y2b <= CY1 
                MOV eax,Mem01 
                ADD eax,MemTemp 
                MOV eax,[eax] 
                MOV c01,eax 
                ;c01 = PeekL(Mem01 + MemTemp) 
              Else 
                c01 = CouleurFond
              EndIf 
            Else 
              c00 = CouleurFond
              c01 = CouleurFond
            EndIf 
            If x2b >= 0 And x2b <= CX1 
              If y2 >= 0 And y2 <= CY1 
                MOV eax,Mem10 
                ADD eax,MemTemp 
                MOV eax,[eax] 
                MOV c10,eax 
                ;c10 = PeekL(Mem10 + MemTemp) 
              Else 
                c10 = CouleurFond
              EndIf 
              If  y2b >= 0 And y2b <= CY1 
                MOV eax,Mem11 
                ADD eax,MemTemp 
                MOV eax,[eax] 
                MOV c11,eax 
                ;c11 = PeekL(Mem11 + MemTemp) 
              Else 
                c11 = CouleurFond
              EndIf 
            Else 
              c10 = CouleurFond
              c11 = CouleurFond
            EndIf 
    
            DefType.l r1,r2,r3,r4 , g1,g2,g3,g4 , b1,b2,b3,b4 

            MOV eax,c00 
            MOV ebx,eax 
            MOV ecx,eax 

            And eax,$FF 
            MOV r1,eax 
            And ebx,$FF00 
            MOV g1,ebx 
            And ecx,$FF0000 
            MOV b1,ecx 

            MOV eax,c10 
            MOV ebx,eax 
            MOV ecx,eax 

            And eax,$FF 
            MOV r2,eax 
            And ebx,$FF00 
            MOV g2,ebx 
            And ecx,$FF0000 
            MOV b2,ecx 

            MOV eax,c01 
            MOV ebx,eax 
            MOV ecx,eax 

            And eax,$FF 
            MOV r3,eax 
            And ebx,$FF00 
            MOV g3,ebx 
            And ecx,$FF0000 
            MOV b3,ecx 

            MOV eax,c11 
            MOV ebx,eax 
            MOV ecx,eax 

            And eax,$FF 
            MOV r4,eax 
            And ebx,$FF00 
            MOV g4,ebx 
            And ecx,$FF0000 
            MOV b4,ecx 
      
            r = r1 * f00 + r2 * f10 + r3 * f01 + r4 * f11   ;pure fait très bien tout ça 
            g = g1 * f00 + g2 * f10 + g3 * f01 + g4 * f11 
            b = b1 * f00 + b2 * f10 + b3 * f01 + b4 * f11 
          
            MOV eax,r 
            MOV ebx,g 
            MOV ecx,b 
            And eax,$FF                                      ;toute l'astuce consiste à laisser les triplets à leur place et à les multiplier là. On évite ainsi les décalages 
            And ebx,$FF00 
            And ecx,$FF0000 
            Or eax,ebx 
            Or eax,ecx 

            MOV ebx,Mem2Temp 
            MOV [ebx],eax 
          
          Else 

            MOV ebx,Mem2Temp 
            MOV eax,CouleurFond 
            MOV [ebx],eax 

          EndIf 
          
          Mem2Temp + 4 
          
        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  d'affichage d'image avec rotation
; On dessine une image

CouleurFondFenetre = GetSysColor_(#COLOR_3DFACE) ; Couleur de fond des fenêtres de Windows

ImageNormale = CreateImage(#PB_Any, 160, 160)
StartDrawing(ImageOutput())
  Box(0, 0, 160, 160, CouleurFondFenetre)
  Box(40, 30, 80, 100, $6F6F6F)
  Box(45, 35, 35, 45, $FF)
  Box(80, 35, 35, 45, $FF00)
  Box(45, 80, 35, 45, $FF0000)
  Box(80, 80, 35, 45, $FFFFFF)
StopDrawing()

ImageRotation = RotateImageEx2(UseImage(ImageNormale), 30, CouleurFondFenetre)

; Création de la fenêtre et de la GadgetList
If OpenWindow(0, 0, 0, 300, 400, #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))

RotationTexte = TextGadget(#PB_Any, 10, 200, 100, 15, "Rotation de 30°")
Rotation = ImageGadget(#PB_Any, 10, 215, 0, 0, UseImage(ImageRotation))

SetTimer_(WindowID(), 0, 25, 0)
Angle = 30
Repeat
  Event = WaitWindowEvent()
  
  If Event = #WM_TIMER
    Angle + 1
    If Angle = 360
      Angle = 0
    EndIf
    FreeImage(ImageRotation)
    ImageRotation = RotateImageEx2(UseImage(ImageNormale), Angle, CouleurFondFenetre)
    SetGadgetState(Rotation, UseImage(ImageRotation))
    SetGadgetText(RotationTexte, "Rotation de " + Str(Angle) + "°")
    
  EndIf
  
Until Event = #PB_EventCloseWindow

KillTimer_(WindowID(), 0)

End
D'ailleurs, je pense que je vais ajouté cette option



Pour voir le principe, remplacer le drawing au début par ceci

Code : Tout sélectionner

ImageNormale = CreateImage(#PB_Any, 160, 160)
StartDrawing(ImageOutput())
  Box(1, 1, 160 - 2, 160 - 2, CouleurFondFenetre)
  Box(40, 30, 80, 100, $6F6F6F)
  Box(45, 35, 35, 45, $FF)
  Box(80, 35, 35, 45, $FF00)
  Box(45, 80, 35, 45, $FF0000)
  Box(80, 80, 35, 45, $FFFFFF)
StopDrawing()

Edité à 12h23

Publié : lun. 21/févr./2005 12:31
par Fred
Effectivement, ca marche avec ton code Regis. Mais le probleme venait du fait que j'ai enlevé une optimisation dans le compilateur et maintenant l'operation -variable/2 ne donne pas forcement le meme resultat qu'avant. Pour avoir le meme resultat faut utiliser (-variable)>>1.

Publié : lun. 21/févr./2005 16:26
par djes
On est moins rapides que Photoshop ?! :cry:
Si tu veux, je peux encore optimiser (avec le mmx, y'a de quoi faire), mais faudra tout passer en asm afin de réutiliser au maximum les registres et éviter les accès mémoire...

Publié : lun. 21/févr./2005 16:40
par Le Soldat Inconnu
:roll: non, c'est bon, ça suffit largement, on a déjà fait mieux que les libs qui existait auparavent :D

Et après, j'arriverais plus à faire des modifs pour ajouter des fonctions. Parce que l'ASM, c'est bien gentil, mais pour s'y retrouver, c'est galère.

Publié : lun. 21/févr./2005 17:08
par Anonyme2
Le Soldat Inconnu a écrit : Et après, j'arriverais plus à faire des modifs pour ajouter des fonctions. Parce que l'ASM, c'est bien gentil, mais pour s'y retrouver, c'est galère.
Mais non, c'est comme le vélo, faut apprendre à pédaler. :D

Publié : lun. 21/févr./2005 18:14
par djes
Le Soldat Inconnu a écrit ::roll: non, c'est bon, ça suffit largement, on a déjà fait mieux que les libs qui existait auparavent :D

Et après, j'arriverais plus à faire des modifs pour ajouter des fonctions. Parce que l'ASM, c'est bien gentil, mais pour s'y retrouver, c'est galère.
Tu as raison, il faut savoir s'arrêter! 8)

Publié : lun. 21/févr./2005 21:41
par Le Soldat Inconnu
Bon, j'ai ajouté 2 nouveaux modes de rotation au choix en fonction du besoin

j'ai également corrigé un petit problème sur le dimensionnement de l'image après rotation.

Voir la lib sur mon site ;)

Code : Tout sélectionner

ProcedureDLL.l RotateImageEx3(ImageID, Angle.f, CouleurFond.l, Mode.l) ; 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 = RGB(Blue(CouleurFond), Green(CouleurFond), Red(CouleurFond))
  
  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)
  Select Mode
    Case 1
      bmi2\bmiHeader\biWidth = bm\bmWidth
      bmi2\bmiHeader\biHeight = bm\bmHeight
    Case 2
      bmi2\bmiHeader\biWidth = Round(Sqr(bm\bmWidth * bm\bmWidth + bm\bmHeight * bm\bmHeight), 1)
      bmi2\bmiHeader\biHeight = bmi2\bmiHeader\biWidth
    Default
      bmi2\bmiHeader\biWidth = Round(bm\bmWidth * Abs(Cos) + bm\bmHeight * Abs(Sin), 1)
      bmi2\bmiHeader\biHeight = Round(bm\bmHeight * Abs(Cos) + bm\bmWidth * Abs(Sin), 1)
  EndSelect
  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
      CX1b = CX1 * 0.5
      CY1b = CY1 * 0.5
      CX2b = CX2 * 0.5
      CY2b = CY2 * 0.5
      
      Mem01 = Mem + bm\bmWidth * 4
      Mem10 = Mem + 4
      Mem11 = Mem01 + 4
      
      Mem2Temp = Mem2
      
      For nn = 0 To CY2
        y1b.f = nn - CY2b
        Temp1.f = CX1b - y1b * Sin
        Temp2.f = CY1b + y1b * Cos
        For n = 0 To CX2
          x1b.f = n - CX2b
          
          x1.f = Temp1 + x1b * Cos
          y1.f = Temp2 + x1b * Sin
          
          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
            f10.f = 1 - fy
            f01.f = f00 * fy
            f00 * f10
            f10 * fx
            f11.f = fx * fy
            
            MemTemp = (x2 + y2 * bm\bmWidth) * 4
            DefType.l c00, c01, c11, c10
            
            If x2 >= 0 And x2 <= CX1
              If y2 >= 0 And y2 <= CY1
                MOV eax, Mem
                ADD eax, MemTemp
                MOV eax, [eax]
                MOV c00, eax
                ; c00 = PeekL(Mem + MemTemp)
              Else
                c00 = CouleurFond
              EndIf
              If y2b >= 0 And y2b <= CY1
                MOV eax, Mem01
                ADD eax, MemTemp
                MOV eax, [eax]
                MOV c01, eax
                ; c01 = PeekL(Mem01 + MemTemp)
              Else
                c01 = CouleurFond
              EndIf
            Else
              c00 = CouleurFond
              c01 = CouleurFond
            EndIf
            If x2b >= 0 And x2b <= CX1
              If y2 >= 0 And y2 <= CY1
                MOV eax, Mem10
                ADD eax, MemTemp
                MOV eax, [eax]
                MOV c10, eax
                ; c10 = PeekL(Mem10 + MemTemp)
              Else
                c10 = CouleurFond
              EndIf
              If y2b >= 0 And y2b <= CY1
                MOV eax, Mem11
                ADD eax, MemTemp
                MOV eax, [eax]
                MOV c11, eax
                ; c11 = PeekL(Mem11 + MemTemp)
              Else
                c11 = CouleurFond
              EndIf
            Else
              c10 = CouleurFond
              c11 = CouleurFond
            EndIf
            
            DefType.l r1, r2, r3, r4, g1, g2, g3, g4, b1, b2, b3, b4
            
            MOV eax, c00
            MOV ebx, eax
            MOV ecx, eax
            
            And eax, $FF
            MOV r1, eax
            And ebx, $FF00
            MOV g1, ebx
            And ecx, $FF0000
            MOV b1, ecx
            
            MOV eax, c10
            MOV ebx, eax
            MOV ecx, eax
            
            And eax, $FF
            MOV r2, eax
            And ebx, $FF00
            MOV g2, ebx
            And ecx, $FF0000
            MOV b2, ecx
            
            MOV eax, c01
            MOV ebx, eax
            MOV ecx, eax
            
            And eax, $FF
            MOV r3, eax
            And ebx, $FF00
            MOV g3, ebx
            And ecx, $FF0000
            MOV b3, ecx
            
            MOV eax, c11
            MOV ebx, eax
            MOV ecx, eax
            
            And eax, $FF
            MOV r4, eax
            And ebx, $FF00
            MOV g4, ebx
            And ecx, $FF0000
            MOV b4, ecx
            
            r = r1 * f00 + r2 * f10 + r3 * f01 + r4 * f11 ; pure fait très bien tout ça
            g = g1 * f00 + g2 * f10 + g3 * f01 + g4 * f11
            b = b1 * f00 + b2 * f10 + b3 * f01 + b4 * f11
            
            MOV eax, r
            MOV ebx, g
            MOV ecx, b
            And eax, $FF ; toute l'astuce consiste à laisser les triplets à leur place et à les multiplier là. On évite ainsi les décalages
            And ebx, $FF00
            And ecx, $FF0000
            Or eax, ebx
            Or eax, ecx
            
            MOV ebx, Mem2Temp
            MOV [ebx], eax
            
          Else
            
            MOV ebx, Mem2Temp
            MOV eax, CouleurFond
            MOV [ebx], eax
            
          EndIf
          
          Mem2Temp + 4
          
        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  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()

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

Angle.f = 30
Mode = 0
CouleurFondFenetre = GetSysColor_(#COLOR_3DFACE) - $101010 ; Couleur de fond des fenêtres de Windows mais légèrement foncé (le - $101010)
ImageRotation = RotateImageEx3(UseImage(ImageNormale), Angle, CouleurFondFenetre, Mode)

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

RotationTexte = TextGadget(#PB_Any, 10, 200, 100, 15, "Rotation de 30°")
Rotation = ImageGadget(#PB_Any, 10, 215, 0, 0, UseImage(ImageRotation))

TextGadget(#PB_Any, 180, 200, 100, 15, "Mode :")
OptionGadget(0, 180, 215, 170, 15, "normal")
OptionGadget(1, 180, 230, 170, 15, "sans redimensionnement")
OptionGadget(2, 180, 245, 170, 15, "avec redimensionnement fixe")
SetGadgetState(0, 1)

SetTimer_(WindowID(), 0, 25, 0)

Repeat
  Event = WaitWindowEvent()
  
  If Event = #WM_TIMER
    Angle + 1
    If Angle = 360
      Angle = 0
    EndIf
    FreeImage(ImageRotation)
    ImageRotation = RotateImageEx3(UseImage(ImageNormale), Angle, CouleurFondFenetre, Mode)
    SetGadgetState(Rotation, UseImage(ImageRotation))
    SetGadgetText(RotationTexte, "Rotation de " + StrF(Angle, 1) + "°")
    
  ElseIf Event = #PB_EventGadget
    Select EventGadgetID()
      Case 0
        Mode = 0
      Case 1 
        Mode = 1
      Case 2
        Mode = 2
    EndSelect
  EndIf
  
Until Event = #PB_EventCloseWindow

KillTimer_(WindowID(), 0)

End

Publié : lun. 21/févr./2005 22:50
par djes
Tant que tu y es, l'ultime truc serait de pouvoir travailler sur des fichiers en multipasses, afin de pouvoir travailler sur de très grandes images, comme photoshop. :twisted:

Publié : lun. 21/févr./2005 23:31
par Le Soldat Inconnu
pfff repos :lol:

Publié : lun. 21/févr./2005 23:38
par djes
Le Soldat Inconnu a écrit :pfff repos :lol:
#jaune glissant: