Fast and clean (antialias) image rotation

Share your advanced PureBasic knowledge/code with the community.
User avatar
djes
Addict
Addict
Posts: 1806
Joined: Sat Feb 19, 2005 2:46 pm
Location: Pas-de-Calais, France

Fast and clean (antialias) image rotation

Post by djes »

Here it is an old code that is part of "le soldat inconnu"'s effect library (http://www.purearea.net/pb/download/userlibs/Effect.zip)
As he seems not to be there anymore, and as this code is not in codearchiv, I release it again on this forum.

Code: Select all

;Fast and clean rotation 
;Original Code : LSI (le soldat inconnu) for his effects library (http://www.purearea.net/pb/download/userlibs/Effect.zip) 
;Optimisation (not fully optimised) by djes (djes@free.fr)
;Not needing assembly inline by psychopanta


;******************************************************************************************************
; RotateImageEx2
;>= Angle (in degrees :()
ProcedureDLL.l RotateImageEx2(ImageID, Angle.f)
  Protected bmi.BITMAPINFO, bmi2.BITMAPINFO, Hdc.l, NewImageID, Mem, n, nn, bm.BITMAP 
  
  ;radian conversion
  Debug "Angle : "+Str(angle)
  Angle*#PI/180 
  
  Protected Cos.f = Cos(Angle) 
  Protected Sin.f = Sin(Angle) 
  
  Protected 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 
    Protected Mem2 = AllocateMemory(bmi2\bmiHeader\biWidth * bmi2\bmiHeader\biHeight * 4) 
    If Mem2 
      
      ;retrieves the bits of the specified bitmap and copies them into a buffer
      Hdc = CreateCompatibleDC_(GetDC_(ImageID)) 
      If Hdc 
        GetDIBits_(Hdc, ImageID, 0, bm\bmHeight, Mem, @bmi, #DIB_RGB_COLORS)
        ReleaseDC_(0, Hdc) 
      EndIf 
      
      Protected CX1 = bm\bmWidth - 1 
      Protected CY1 = bm\bmHeight - 1 
      Protected CX2 = bmi2\bmiHeader\biWidth - 1 
      Protected CY2 = bmi2\bmiHeader\biHeight - 1 
      
      Protected Mem01 = Mem + bm\bmWidth * 4 
      Protected Mem10 = Mem + 4 
      Protected Mem11 = Mem01 + 4 
      
      Protected Mem2Temp = Mem2 
      Protected deb=-CX2/2
      Protected fin=deb+CX2;= Round(CX2/2,1) but <> (CX2*2-CX2)/2 
          
      For nn = 0 To CY2 

        Protected x1b.l
        Protected y1b.l = (nn * 2) - CY2 

        Protected Temp1.f = (CX1 - (y1b * Sin))/2
        Protected Temp2.f = (CY1 + (y1b * Cos))/2       

        Protected x1.f = Temp1 + (deb * Cos)
        Protected y1.f = Temp2 + (deb * Sin)

        For x1b = deb To fin 
          
          ;could be faster with arrays
          
          Protected x2.l = x1 
          Protected y2.l = y1 
          
          If x1 < x2 
            !dec dword[p.v_x2] 
          EndIf 
          If y1 < y2 
            !dec dword[p.v_y2] 
          EndIf 
          
          Protected x2b.l = x2 + 1 
          Protected y2b.l = y2 + 1 
          
          ;test boundaries
          If x2b >= 0 And x2 <= CX1 And y2b >= 0 And y2 <= CY1  
          
            Protected fx.f = x1 - x2 
            Protected fy.f = y1 - y2 
            Protected f00.f = 1 - fx 
            Protected f10.f = 1 - fy 
            Protected f01.f = f00 * fy 
            f00 * f10 
            f10 * fx 
            Protected f11.f = fx * fy 
          
            Protected MemTemp = (x2 + y2 * bm\bmWidth) * 4 
            Protected c00.l, c01.l, c11.l, c10.l 
            
            If x2 >= 0 And x2 <= CX1 
              If y2 >= 0 And y2 <= CY1 
                !mov eax,dword[p.v_Mem] 
                !add eax,dword[p.v_MemTemp] 
                !mov eax,dword[eax] 
                !mov dword[p.v_c00],eax 
                ;c00 = PeekL(Mem + MemTemp) 
              Else 
                c00 = 0 
              EndIf 
              If y2b >= 0 And y2b <= CY1 
                !mov eax,dword[p.v_Mem01] 
                !add eax,dword[p.v_MemTemp] 
                !mov eax,dword[eax] 
                !mov dword[p.v_c01],eax 
                ;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 
                !mov eax,dword[p.v_Mem10] 
                !add eax,dword[p.v_MemTemp] 
                !mov eax,dword[eax] 
                !mov dword[p.v_c10],eax 
                ;c10 = PeekL(Mem10 + MemTemp) 
              Else 
                c10 = 0 
              EndIf 
              If  y2b >= 0 And y2b <= CY1 
                !mov eax,dword[p.v_Mem11] 
                !add eax,dword[p.v_MemTemp] 
                !mov eax,dword[eax] 
                !mov dword[p.v_c11],eax 
                ;c11 = PeekL(Mem11 + MemTemp) 
              Else 
                c11 = 0 
              EndIf 
            Else 
              c10 = 0 
              c11 = 0 
            EndIf 
    
            Protected r1.l,r2.l,r3.l,r4.l,g1.l,g2.l,g3.l,g4.l,b1.l,b2.l,b3.l,b4.l 

            !mov eax,dword[p.v_c00] 
            !mov ebx,eax 
            !mov ecx,eax 

            !and eax,$FF 
            !mov dword[p.v_r1],eax 
            !and ebx,$FF00 
            !mov dword[p.v_g1],ebx 
            !and ecx,$FF0000 
            !mov dword[p.v_b1],ecx 

            !mov eax,dword[p.v_c10] 
            !mov ebx,eax 
            !mov ecx,eax 

            !and eax,$FF 
            !mov dword[p.v_r2],eax 
            !and ebx,$FF00 
            !mov dword[p.v_g2],ebx 
            !and ecx,$FF0000 
            !mov dword[p.v_b2],ecx 

            !mov eax,dword[p.v_c01] 
            !mov ebx,eax 
            !mov ecx,eax 

            !and eax,$FF 
            !mov dword[p.v_r3],eax 
            !and ebx,$FF00 
            !mov dword[p.v_g3],ebx 
            !and ecx,$FF0000 
            !mov dword[p.v_b3],ecx 

            !mov eax,dword[p.v_c11] 
            !mov ebx,eax 
            !mov ecx,eax 

            !and eax,$FF 
            !mov dword[p.v_r4],eax 
            !and ebx,$FF00 
            !mov dword[p.v_g4],ebx 
            !and ecx,$FF0000 
            !mov dword[p.v_b4],ecx 
      
           ;pure knows well how to do this 
            Protected r.l = r1 * f00 + r2 * f10 + r3 * f01 + r4 * f11
            Protected g.l = g1 * f00 + g2 * f10 + g3 * f01 + g4 * f11 
            Protected b.l = b1 * f00 + b2 * f10 + b3 * f01 + b4 * f11 
          
            !mov eax,dword[p.v_r] 
            !mov ebx,dword[p.v_g] 
            !mov ecx,dword[p.v_b]
            ;one trick is to let triplets at the same place to avoid shifting
            !and eax,$FF                                      
            !and ebx,$FF00 
            !and ecx,$FF0000 
            !or eax,ebx 
            !or eax,ecx 

            !mov ebx,dword[p.v_Mem2Temp] 
            !mov dword[ebx],eax 
          
          Else 

            !mov ebx,dword[p.v_Mem2Temp] 
            !xor eax,eax 
            !mov dword[ebx],eax 

          EndIf 
          
          Mem2Temp + 4 
          x1 + cos
          y1 + sin
          
        Next 
      Next 
      
      NewImageID = CreateImage(#PB_Any, bmi2\bmiHeader\biWidth, bmi2\bmiHeader\biHeight) 
      Hdc = CreateCompatibleDC_(GetDC_(ImageID(NewImageID))) 
      If Hdc 
        ;copy
        SetDIBits_(Hdc, ImageID(NewImageID), 0, bmi2\bmiHeader\biHeight, Mem2, @bmi2, #DIB_RGB_COLORS)
        ReleaseDC_(0, Hdc) 
      EndIf 
      
      FreeMemory(Mem2) 
    EndIf 
    FreeMemory(Mem) 
  EndIf 
  
  ProcedureReturn NewImageID 
EndProcedure 

;******************************************************************************************************
;- Speed Test

SetPriorityClass_(GetCurrentProcess_(),#REALTIME_PRIORITY_CLASS) 

#NbTest = 4 

MessageRequester("Speed test",Str(#NbTest)+" rotations of a 1000x1000 image...") 

BigImage = CreateImage(#PB_Any, 1000, 1000) 
If BigImage<>0 
  StartDrawing(ImageOutput(BigImage)) 
    For n = 0 To 999 
      For nn = 0 To 999 
        Plot(n, nn, Random($FFFFFF)) 
      Next 
    Next 
  StopDrawing() 
  
  Dim Liste(ImageWidth(BigImage) - 1, ImageHeight(BigImage) - 1) 
  
  Time1 = ElapsedMilliseconds() 
  
  For n = 1 To #NbTest 
    DestImage = RotateImageEx2(ImageID(BigImage), 30) 
  Next 
  
  Time2 = ElapsedMilliseconds() 
  
  Speed = (Time2 - Time1) / #NbTest 
  NbPixels = ImageHeight(BigImage) * ImageWidth(BigImage) 
  
  MessageRequester("Results", "Average speed of "+Str(Speed) + " ms" + Chr(10) + "Image of " + Str(ImageWidth(BigImage)) + " * " + Str(ImageHeight(BigImage)) + " pixels" + Chr(10) + "Pixels nb = " + Str(NbPixels), 0) 
EndIf 

;******************************************************************************************************
;- Drawing test 

SrcImage = CreateImage(#PB_Any, 80, 100) 

If SrcImage<>0 
  StartDrawing(ImageOutput(SrcImage)) 
    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() 
  
  RotImage = RotateImageEx2(ImageID(SrcImage), u)  

EndIf 

SetPriorityClass_(GetCurrentProcess_(),#NORMAL_PRIORITY_CLASS) 

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

TextGadget(#PB_Any, 10, 10, 100, 15, "Src Image") 
ImageGadget(#PB_Any, 10, 25, 0, 0, ImageID(SrcImage)) 

TextGadget(1, 10, 135, 100, 15, "Rotation") 
ImageGadget(2, 10, 150, 0, 0, ImageID(RotImage)) 

angle = 1

Repeat

  Event = WindowEvent() 
  Delay(20)

  RotImage1 = ImageID(RotateImageEx2(ImageID(SrcImage), angle))

  SetGadgetText(1, "Rotation : " + Str(angle))
  SetGadgetState(2, RotImage1)

  If IsImage(RotImage2) : FreeImage(RotImage2) : Delay(20) : EndIf

  angle + 1

  RotImage2 = ImageID(RotateImageEx2(ImageID(SrcImage), angle))

  SetGadgetText(1, "Rotation : " + Str(angle))
  SetGadgetState(2, RotImage2)

  If IsImage(RotImage1) : FreeImage(RotImage1) : Delay(20) : EndIf

  angle + 1
  

Until Event = #PB_Event_CloseWindow 

End
; IDE Options = PureBasic v4.02 (Windows - x86)
; CursorPosition = 4
; Folding = -
; DisableDebugger
Last edited by djes on Mon Oct 08, 2007 8:02 pm, edited 3 times in total.
User avatar
luis
Addict
Addict
Posts: 3895
Joined: Wed Aug 31, 2005 11:09 pm
Location: Italy

Post by luis »

Thank you, very useful!
User avatar
Rook Zimbabwe
Addict
Addict
Posts: 4322
Joined: Tue Jan 02, 2007 8:16 pm
Location: Cypress TX
Contact:

Post by Rook Zimbabwe »

with this:

Code: Select all

 
         If x1 < x2 
            DEC x2 
          EndIf 
          If y1 < y2 
            DEC y2 
          EndIf 
the DEC returns a Syntax error in PB 4.02

I know this is ASM... what do I not have turned on???
ahhh Enable Inline ASM... stupid me!

4031ms... not exactly speedy
Last edited by Rook Zimbabwe on Thu Oct 04, 2007 9:11 pm, edited 1 time in total.
Binarily speaking... it takes 10 to Tango!!!

Image
http://www.bluemesapc.com/
milan1612
Addict
Addict
Posts: 894
Joined: Thu Apr 05, 2007 12:15 am
Location: Nuremberg, Germany
Contact:

Post by milan1612 »

You forgot to enable inline assembler in the compiler options :wink:
Windows 7 & PureBasic 4.4
User avatar
luis
Addict
Addict
Posts: 3895
Joined: Wed Aug 31, 2005 11:09 pm
Location: Italy

Post by luis »

Rook Zimbabwe wrote:
4031ms... not exactly speedy
Disable debugger.
byo
Enthusiast
Enthusiast
Posts: 635
Joined: Mon Apr 02, 2007 1:43 am
Location: Brazil

Post by byo »

Wow, thanks. Wonderful.
Please, keep posting your graphic manipulation techniques as seen in your games. It's very helpful when one knows a lot about graphics + assembly.

Keep up the good work.
User avatar
djes
Addict
Addict
Posts: 1806
Joined: Sat Feb 19, 2005 2:46 pm
Location: Pas-de-Calais, France

Post by djes »

I'm proud to say that I'm a kind of rotation specialist :)
On amiga 1200, I've done a rotation with only two 68020 operands, I think it was one of the fastest (except sanity with blitter on Amiga 500 :P)
User avatar
Psychophanta
Always Here
Always Here
Posts: 5153
Joined: Wed Jun 11, 2003 9:33 pm
Location: Anare
Contact:

Post by Psychophanta »

Nice! djes.
Just modified to not to have to enable inline ASM:

Code: Select all

;Fast and clean rotation
;Original Code : LSI (le soldat inconnu) for his effects library (http://www.purearea.net/pb/download/userlibs/Effect.zip)
;Optimisation (not fully optimised) by djes (djes@free.fr)

;#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
 
  Angle*#PI/180 ; On convertit en radian
 
  Protected Cos.f = Cos(Angle)
  Protected Sin.f = Sin(Angle)
 
  Protected 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
    Protected 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
     
      Protected CX1 = bm\bmWidth - 1
      Protected CY1 = bm\bmHeight - 1
      Protected CX2 = bmi2\bmiHeader\biWidth - 1
      Protected CY2 = bmi2\bmiHeader\biHeight - 1
     
      Protected Mem01 = Mem + bm\bmWidth * 4
      Protected Mem10 = Mem + 4
      Protected Mem11 = Mem01 + 4
     
      Protected Mem2Temp = Mem2

      Protected deb=-CX2/2 : Protected fin=(CX2*2-CX2)/2
     
      For nn = 0 To CY2
        Protected y1b.l = nn * 2 - CY2
        Protected Temp1.f = (CX1 - y1b * Sin)/2
        Protected Temp2.f = (CY1 + y1b * Cos)/2
        Protected x1b.l
        For x1b = deb To fin
         
          Protected x1.f = Temp1 + x1b * Cos  ;on pourrait virer ces mult avec des tables mais le gain n'est pas évident
          Protected y1.f = Temp2 + x1b * Sin
         
          Protected x2.l = x1
          Protected y2.l = y1
         
          If x1 < x2
            !dec dword[p.v_x2]
          EndIf
          If y1 < y2
            !dec dword[p.v_y2]
          EndIf
         
          Protected x2b = x2 + 1
          Protected 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
         
            Protected fx.f = x1 - x2
            Protected fy.f = y1 - y2
            Protected f00.f = 1 - fx
            Protected f10.f = 1 - fy
            Protected f01.f = f00 * fy
            f00 * f10
            f10 * fx
            Protected f11.f = fx * fy
         
            Protected MemTemp = (x2 + y2 * bm\bmWidth) * 4
            Protected c00.l, c01.l, c11.l, c10.l
           
            If x2 >= 0 And x2 <= CX1
              If y2 >= 0 And y2 <= CY1
                !mov eax,dword[p.v_Mem]
                !add eax,dword[p.v_MemTemp]
                !mov eax,dword[eax]
                !mov dword[p.v_c00],eax
                ;c00 = PeekL(Mem + MemTemp)
              Else
                c00 = 0
              EndIf
              If y2b >= 0 And y2b <= CY1
                !mov eax,dword[p.v_Mem01]
                !add eax,dword[p.v_MemTemp]
                !mov eax,dword[eax]
                !mov dword[p.v_c01],eax
                ;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
                !mov eax,dword[p.v_Mem10]
                !add eax,dword[p.v_MemTemp]
                !mov eax,dword[eax]
                !mov dword[p.v_c10],eax
                ;c10 = PeekL(Mem10 + MemTemp)
              Else
                c10 = 0
              EndIf
              If  y2b >= 0 And y2b <= CY1
                !mov eax,dword[p.v_Mem11]
                !add eax,dword[p.v_MemTemp]
                !mov eax,dword[eax]
                !mov dword[p.v_c11],eax
                ;c11 = PeekL(Mem11 + MemTemp)
              Else
                c11 = 0
              EndIf
            Else
              c10 = 0
              c11 = 0
            EndIf
   
            Protected r1.l,r2.l,r3.l,r4.l,g1.l,g2.l,g3.l,g4.l,b1.l,b2.l,b3.l,b4.l

            !mov eax,dword[p.v_c00]
            !mov ebx,eax
            !mov ecx,eax

            !and eax,$FF
            !mov dword[p.v_r1],eax
            !and ebx,$FF00
            !mov dword[p.v_g1],ebx
            !and ecx,$FF0000
            !mov dword[p.v_b1],ecx

            !mov eax,dword[p.v_c10]
            !mov ebx,eax
            !mov ecx,eax

            !and eax,$FF
            !mov dword[p.v_r2],eax
            !and ebx,$FF00
            !mov dword[p.v_g2],ebx
            !and ecx,$FF0000
            !mov dword[p.v_b2],ecx

            !mov eax,dword[p.v_c01]
            !mov ebx,eax
            !mov ecx,eax

            !and eax,$FF
            !mov dword[p.v_r3],eax
            !and ebx,$FF00
            !mov dword[p.v_g3],ebx
            !and ecx,$FF0000
            !mov dword[p.v_b3],ecx

            !mov eax,dword[p.v_c11]
            !mov ebx,eax
            !mov ecx,eax

            !and eax,$FF
            !mov dword[p.v_r4],eax
            !and ebx,$FF00
            !mov dword[p.v_g4],ebx
            !and ecx,$FF0000
            !mov dword[p.v_b4],ecx
     
            Protected r.l = r1 * f00 + r2 * f10 + r3 * f01 + r4 * f11   ;pure fait très bien tout ça
            Protected g.l = g1 * f00 + g2 * f10 + g3 * f01 + g4 * f11
            Protected b.l = b1 * f00 + b2 * f10 + b3 * f01 + b4 * f11
         
            !mov eax,dword[p.v_r]
            !mov ebx,dword[p.v_g]
            !mov ecx,dword[p.v_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,dword[p.v_Mem2Temp]
            !mov dword[ebx],eax
         
          Else

            !mov ebx,dword[p.v_Mem2Temp]
            !xor eax,eax
            !mov dword[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(NewImageID)))
      If Hdc
        SetDIBits_(Hdc, ImageID(NewImageID), 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é

SetPriorityClass_(GetCurrentProcess_(),#REALTIME_PRIORITY_CLASS)

ImageOrigine = CreateImage(#PB_Any, 1000, 1000)
If ImageOrigine<>0
  StartDrawing(ImageOutput(ImageOrigine))
    For n = 0 To 999
      For nn = 0 To 999
        Plot(n, nn, Random($FFFFFF))
      Next
    Next
  StopDrawing()
 
  Dim Liste(ImageWidth(ImageOrigine) - 1, ImageHeight(ImageOrigine) - 1)
 
  #NbTest = 4
 
  Temps1 = ElapsedMilliseconds()
 
  For n = 1 To #NbTest
    ImageModifiee = RotateImageEx2(ImageID(ImageOrigine), 30)
  Next
 
  Temps2 = ElapsedMilliseconds()
 
  Vitesse = (Temps2 - Temps1) / #NbTest
  NbPixel = ImageHeight(ImageOrigine) * ImageWidth(ImageOrigine)
 
  MessageRequester("Temps", Str(Vitesse) + " ms" + Chr(10) + "Image de " + Str(ImageWidth(ImageOrigine)) + " * " + Str(ImageHeight(ImageOrigine)) + " pixels" + Chr(10) + "Nb pixels traités = " + Str(NbPixel), 0)
EndIf


;-----------------------------------------
;- Test  d'affichage d'image avec rotation
; On dessine une image
ImageNormale = CreateImage(#PB_Any, 80, 100)

If ImageNormale<>0
  StartDrawing(ImageOutput(ImageNormale))
    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(ImageID(ImageNormale), 30)

EndIf

SetPriorityClass_(GetCurrentProcess_(),#NORMAL_PRIORITY_CLASS)

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

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

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

Repeat
  Event = WaitWindowEvent()
 
Until Event = #PB_Event_CloseWindow

End
http://www.zeitgeistmovie.com

while (world==business) world+=mafia;
User avatar
djes
Addict
Addict
Posts: 1806
Joined: Sat Feb 19, 2005 2:46 pm
Location: Pas-de-Calais, France

Post by djes »

Thank you psychopanta! As I said, original code was not mine, "Le soldat inconnu" didn't want that I go too far in optimisation, and it was for a DLL, so inline was not a problem. But it's better with your modifications :)
User avatar
Rings
Moderator
Moderator
Posts: 1435
Joined: Sat Apr 26, 2003 1:11 am

Post by Rings »

have you guys tried to use an angle like 40° ?

the rotated picture looks ugly.
SPAMINATOR NR.1
User avatar
DoubleDutch
Addict
Addict
Posts: 3220
Joined: Thu Aug 07, 2003 7:01 pm
Location: United Kingdom
Contact:

Post by DoubleDutch »

If used for games where the rotation is only seen for a split second, it doesn't matter if it's ugly - it just matters that its fast.
https://deluxepixel.com <- My Business website
https://reportcomplete.com <- School end of term reports system
User avatar
djes
Addict
Addict
Posts: 1806
Joined: Sat Feb 19, 2005 2:46 pm
Location: Pas-de-Calais, France

Post by djes »

Rings wrote:have you guys tried to use an angle like 40° ?

the rotated picture looks ugly.
Sorry, you were right, there was a bug. I've corrected it and reposted (first message)

Thank you!
User avatar
djes
Addict
Addict
Posts: 1806
Joined: Sat Feb 19, 2005 2:46 pm
Location: Pas-de-Calais, France

Post by djes »

DoubleDutch wrote:If used for games where the rotation is only seen for a split second, it doesn't matter if it's ugly - it just matters that its fast.
No, the image is a bit antialiased (4 points average) :)
User avatar
Rings
Moderator
Moderator
Posts: 1435
Joined: Sat Apr 26, 2003 1:11 am

Post by Rings »

djes wrote:
Rings wrote:have you guys tried to use an angle like 40° ?

the rotated picture looks ugly.
Sorry, you were right, there was a bug. I've corrected it and reposted (first message)

Thank you!
thank you for a working version/snippet,
very usefull for my actual project.
SPAMINATOR NR.1
User avatar
Rook Zimbabwe
Addict
Addict
Posts: 4322
Joined: Tue Jan 02, 2007 8:16 pm
Location: Cypress TX
Contact:

Post by Rook Zimbabwe »

Disabling DeBugger... yeilds QUITE an improvement!!!
Binarily speaking... it takes 10 to Tango!!!

Image
http://www.bluemesapc.com/
Post Reply