Seite 1 von 3

Bilder drehen

Verfasst: 20.11.2018 21:38
von ccode_new
Hallo!

Hat jemand spontan eine schnelle Procedure um Bilder (keine Sprites) zu drehen ?

Also nicht so etwas langsames wie:

Code: Alles auswählen

Procedure RotiereEinBild(bild, richtung)
 Protected i.i, k.i
 Protected rbild.i
 Protected w.i = ImageWidth(bild)
 Protected h.i = ImageHeight(bild)
 Protected Dim p(w,h)
 
  If IsImage(bild)
    
    ;Lese die Pixel
    StartDrawing( ImageOutput(bild) )
      For k=0 To h-1
        For i=0 To w-1
          p(i,k)=Point(i,k)
        Next
      Next
    StopDrawing()
    
    ;Drehrichtung
    If richtung = 0 ;"90° oder Pi/2"
      If w<>h
        Swap w,h
        rbild = CreateImage(#PB_Any,w+1,h+1)
        If IsImage(rbild)
          FreeImage(bild)
        EndIf
      EndIf
      
      StartDrawing( ImageOutput(rbild) )
      For k=0 To h
        For i=0 To w
          Plot(i,k, p(k,w-i))
        Next
      Next
      StopDrawing()
    ElseIf richtung = 1 ;"180° oder Pi"
      rbild = CreateImage(#PB_Any,w+1,h+1)
      If IsImage(rbild)
        FreeImage(bild)
      EndIf
      
      StartDrawing( ImageOutput(rbild) )
      For k=0 To h-1
        For i=0 To w-1
          kk = (h-1)-k
          ii = (w-1)-i
          Plot(i,k, p(ii,kk))
        Next
      Next
      StopDrawing()
    ElseIf richtung = 2 ;"270° oder 3/2 * Pi"
      If w<>h
        Swap w,h
        rbild = CreateImage(#PB_Any,w+1,h+1)
        If IsImage(rbild)
          FreeImage(bild)
        EndIf
      EndIf
      
      StartDrawing( ImageOutput(rbild) )
      For k=0 To h
        For i=0 To w
          kk = (h)-k
          ii = (w)-i
          Plot(i,k, p(kk,ii))
        Next
      Next
      StopDrawing()
    EndIf
 
    ProcedureReturn rbild
  EndIf
EndProcedure
Bitte keine OpenGL-Lösungen mit glScale,... oder Shader wie:

Code: Alles auswählen

uniform sampler2D color_texture;
uniform vec2 resolution;

void main(){
    float angle = 1.570796327; //270°
    vec2 pos = gl_FragCoord.xy/resolution;
    pos.x = 1.0 - pos.x;
    float sin_factor = sin(angle);
    float cos_factor = cos(angle);
    pos = (-pos - 0.5) * mat2(cos_factor, sin_factor, -sin_factor, cos_factor);
    pos += 0.5;

    gl_FragColor = texture2D(color_texture, -pos);
}
Achso noch etwas:

Die Procedure sollte nicht nur mit 32bit Farbtiefe klarkommen, sondern auch mit anderen Farbtiefen (24bit).
Und die Procedure sollte mit hohen Auflösungen (> 20 Megapixel) klarkommen.

Re: Bilder drehen

Verfasst: 20.11.2018 22:34
von NicTheQuick
Ich hab das hier gefunden, aber nicht getestet, da das wohl nur unter Windows geht: https://www.purebasic.fr/english/viewto ... 12&t=38975

Re: Bilder drehen

Verfasst: 20.11.2018 23:02
von ccode_new
@Nic

Genial!
(Vor allem die freie Rotation)

-> Nur leider ist meine gepostete Procedure schneller.

nImgOut = RotateImage(nImgSrc, 90)
nImgOut = RotiereEinBild(nImgSrc, 0) ;Ist schneller!

Re: Bilder drehen

Verfasst: 21.11.2018 00:20
von ccode_new
Naja, wegen der Vollständigkeit:

Mit Vector-Drawing bin ich am flexibelsten, aber leider noch langsamer.

Code: Alles auswählen

Procedure RotiereEinBild(bild, richtung)
  Protected rbild.i
  If IsImage(bild)
    If richtung = 0
      ;90°
      rbild = Createbild(#PB_Any, ImageHeight(bild), ImageWidth(bild))
      If StartVectorDrawing(ImageVectorOutput(rbild))
        MovePathCursor((ImageWidth(rbild)/2)+(ImageHeight(bild)/2), 0)
        RotateCoordinates(0, 0, 90)
        DrawVectorbild(ImageID(bild))
        StopVectorDrawing()
      EndIf
    ElseIf richtung = 1
      ;180°
      rbild = Createbild(#PB_Any, ImageWidth(bild), ImageHeight(bild))
      If StartVectorDrawing(ImageVectorOutput(rbild))
        MovePathCursor((ImageWidth(rbild)/2)+(ImageWidth(bild)/2), (ImageHeight(rbild)/2)+(ImageHeight(bild)/2))
        RotateCoordinates(0, 0, 180)
        DrawVectorbild(ImageID(bild))
        StopVectorDrawing()
      EndIf
    ElseIf richtung = 2
      ;270°
      rbild = Createbild(#PB_Any, ImageHeight(bild), ImageWidth(bild))
      If StartVectorDrawing(ImageVectorOutput(rbild))
        MovePathCursor(0, ImageHeight(rbild))
        RotateCoordinates(0, 0, 270)
        DrawVectorbild(ImageID(bild))
        StopVectorDrawing()
      EndIf
    EndIf
    ProcedureReturn rbild
  EndIf
EndProcedure

Re: Bilder drehen

Verfasst: 21.11.2018 21:58
von ccode_new
Guten Abend!

Das hier funktioniert auch für verschiedene Zwecke und ist schnell:

Code: Alles auswählen

Procedure PropSize(oldWidth, oldHeight, newWidth, newHeight = #PB_Any)
  If newHeight = #PB_Any
    ProcedureReturn newWidth * oldHeight / oldWidth
  Else
    ProcedureReturn newHeight * oldWidth / oldHeight
  EndIf
EndProcedure

Procedure RotateImage_(img.s, dir, w, h) ;img = Übergabe des Bildpfades
  Protected rspr.i, tmp_rspr.i, rimg.i
  rspr = LoadSprite(#PB_Any, img)
  If IsSprite(rspr)
    ZoomSprite(rspr, PropSize(SpriteWidth(rspr), SpriteHeight(rspr), #PB_Any, h), h)
    If dir = 0
      RotateSprite(rspr, 90, #PB_Absolute)
    ElseIf dir = 1
      RotateSprite(rspr, 180, #PB_Absolute)
    ElseIf dir = 2
      RotateSprite(rspr, 270, #PB_Absolute)
    EndIf
    ClearScreen(RGB(0,0,0))
    DisplaySprite(rspr,(w/2)-(SpriteWidth(rspr)/2), (h/2)-(SpriteHeight(rspr)/2))
    tmp_rspr = GrabSprite(#PB_Any, 0, 0, w, h)
    If IsSprite(tmp_rspr)
      FreeSprite(rspr)
    EndIf
    StartDrawing(SpriteOutput(tmp_rspr))
    rimg = GrabDrawingImage(#PB_Any, 0, 0, SpriteWidth(tmp_rspr), SpriteHeight(tmp_rspr))
    StopDrawing()
    ProcedureReturn rimg
  Else
    Debug "Fehler!"
  EndIf
EndProcedure
,... aber:

Die Renderqualität ist schlechter !!!
Und bei vielen Bildern funktioniert Rotate/Zoom/Grab-Sprite nicht und man erhält leider nur ein weißes Bild.

Re: Bilder drehen

Verfasst: 21.11.2018 22:22
von HeX0R
Ich denke mit DrawingBuffer() und co. solltest Du wesentlich schneller sein, als Dein Plot/Point-Gedöns.

[Edit]
Hier gibts sowas:
https://www.purebasic.fr/english/viewtopic.php?p=437885

Weiterlesen! Da sind noch mehr Codes drin.

Re: Bilder drehen

Verfasst: 21.11.2018 22:46
von ccode_new
Hallo HeXOR!

Alle von mir getesteten Varianten mit DrawingBuffer() sind nicht schneller/bzw. gleich schnell mit der ersten geposteten Procedure.

Ich glaube die Plot/Point - Funktionen von PureBasic sind schon dahingehend optimiert wurden.

Du bist am Zug mir eine schnellere Procedure zu liefern. ;)

Anbei:
Das mit den weißen Bildern liegt an zu großen Bildern. Diese Texturegrößen kann die Sprite-Lib/bzw. die GPU nicht mehr (direkt) verarbeiten.
(>= 20 Megapixel-Bilder !!!)

Hier würde eine gute Resize-Funktion helfen! Hat da jemand Tipps!

Re: Bilder drehen

Verfasst: 21.11.2018 22:54
von NicTheQuick
Darf ich den Hintergrund erfahren, warum du das machen willst? 20 MP kannst du ja eh nicht am Stück auf einem Bildschirm anzeigen. Aber wenn du zum Anzeigen zum Beispiel immer nur den Teil drehst, der aktuell angezeigt wird, dann sollte das doch recht flott gehen, oder?
Und hast du den Debugger deaktiviert? Damit geht alles sehr viel langsamer.

Re: Bilder drehen

Verfasst: 21.11.2018 23:00
von ccode_new
@Nic

Ja ich möchte/ muss die Bilder auch "Resizen".

Das mache ich auch.

Aber wenn ich über Sprites rotieren möchte (weil es schneller ist) dann brauche ich eine Resize-Funktion für Sprites!

ZoomSprite() bringt dann nämlich nichts! (Funktioniert dann nicht!)

ResizeImage() funktioniert aber gut, geht aber nur mit Bilder (und nicht mit Sprites).

Re: Bilder drehen

Verfasst: 21.11.2018 23:06
von ts-soft
Nicht ganz Ernst gemeint!
Die schnellste Möglichkeit Bilder, bzw. den Bildschirm zu drehen unter Windows ist die hier abgebildete:
Bild