Aktuelle Zeit: 25.04.2019 20:14

Alle Zeiten sind UTC + 1 Stunde [ Sommerzeit ]




Ein neues Thema erstellen Auf das Thema antworten  [ 7 Beiträge ] 
Autor Nachricht
 Betreff des Beitrags: Image spiegeln
BeitragVerfasst: 20.09.2018 12:29 
Offline

Registriert: 01.04.2011 21:59
Hallo Gemeinde,

ich habe für ein kleines Programm die schnelle Spiegelung von Images benötigt und wollte Euch meine "geistigen Ergüsse" nicht vorenthalten. :lol:

Wichtig dabei: ich arbeite immer mit 32 Bit Farbtiefe. Nur dann funktioniert das vertikale Spiegeln. Es gibt durchaus Images mit weniger Farbtiefe... diese müsste man dann ggf. konvertieren oder die Routine etwas umbauen, was sie aber wieder langsamer machen würde...
Code:
EnableExplicit

Structure einzeln                                     ; Zugriff auf die einzenen Farbkanäle
  pix_r.a
  pix_g.a
  pix_b.a
  pix_a.a
EndStructure

Structure pixel                                       ; Zugriff auf komplettes Pixel oder Farbkanäle
  StructureUnion
    pix_l.l
    pix.einzeln
  EndStructureUnion
EndStructure

Procedure hspiegeln(image)
  Protected zeilenlaenge                              ; Länge (in Byte) einer Zeile im Image
  Protected hoehe                                     ; Image-Höhe
  Protected tiefe                                     ; Farbtiefe des Images in Byte (echte Tiefe im Speicher)
  Protected *obere.pixel                              ; Adresse der oberen Zeile im Speicher
  Protected *untere.pixel                             ; Adresse der unteren Zeile im Speicher
  Protected i                                         ; Laufvariable
  Protected halbe_hoehe                               ; Image-Höhe / 2 für optimierten Durchlauf
  Protected *zeilenpuffer                             ; Zwischenspeicher für 1 Zeile
 
  ; Daten über das Image holen
  StartDrawing(ImageOutput(image))
    *obere.pixel = DrawingBuffer()
    zeilenlaenge = DrawingBufferPitch()
  StopDrawing()
  *zeilenpuffer = AllocateMemory(zeilenlaenge)
  hoehe = ImageHeight(image)
  tiefe = ImageDepth(image) / 8                       ; Bytes pro Pixel
  halbe_hoehe = hoehe / 2                             ; in eine Durchlauf linkes und rechtes Pixel tauschen, daher muss nur die halbe Länge durchlaufen werden
  *untere = *obere + (zeilenlaenge * (hoehe-1))       ; Adresse der unteren Zeile ermitteln
 
  For i = 1 To halbe_hoehe
    CopyMemory(*obere, *zeilenpuffer, zeilenlaenge)   ; obere Zeile merken
    CopyMemory(*untere, *obere, zeilenlaenge)         ; untere Zeile in obere Zeile
    CopyMemory(*zeilenpuffer, *untere, zeilenlaenge)  ; obere Zeile in untere zeile
    *obere + zeilenlaenge
    *untere - zeilenlaenge
  Next i
  FreeMemory(*zeilenpuffer)
EndProcedure

Procedure vspiegeln(image)
  Protected zeilenlaenge                              ; Länge (in Byte) einer Zeile im Image
  Protected hoehe                                     ; Image-Höhe
  Protected breite                                    ; Image-Breite
  Protected tiefe                                     ; Farbtiefe des Images in Byte (echte Tiefe im Speicher)
  Protected *linkes.pixel                             ; Adresse des linken Pixels im Speicher
  Protected *rechtes.pixel                            ; Adresse des rechten Pixels im Speicher
  Protected i, j, k                                   ; Laufvariablen
  Protected halbe_breite                              ; Image-Breite / 2 für optimierten Durchlauf
  Protected farbpuffer                                ; Zwischenspeicher für 1 Pixel
 
  ; Daten über das Image holen
  StartDrawing(ImageOutput(image))
    *linkes.pixel = DrawingBuffer()
    zeilenlaenge = DrawingBufferPitch()
  StopDrawing()
  hoehe = ImageHeight(image)
  breite = ImageWidth(image)
  tiefe = ImageDepth(image) / 8                       ; Bytes pro Pixel
  halbe_breite = breite / 2                           ; in eine Durchlauf linkes und rechtes Pixel tauschen, daher muss nur die halbe Länge durchlaufen werden
 
  If tiefe = 4
    For i = 1 To hoehe
      k = zeilenlaenge                               
      *rechtes = *linkes + (tiefe * (breite-1))       ; Adresse des letzten Pixels in der Zeile
      For j = 1 To halbe_breite
        farbpuffer = *linkes\pix_l                    ; Farbe des linken Pixels merken
        *linkes\pix_l = *rechtes\pix_l                ; Farbe des rechten Pixels in linkes Pixel
        *rechtes\pix_l = farbpuffer                   ; Farbe des linken Pixels in rechtes Pixel
       
        *linkes + tiefe                               ; nächstes Pixel links
        *rechtes - tiefe                              ; nächstes Pixel rechts
        k - tiefe
      Next
      *linkes + k                                     ; Start der nächsten Zeile
    Next
  Else
    Debug "VSpiegeln(): Image-Tiefe ist nicht 32Bit!"
  EndIf
EndProcedure

; --- Beispiel
UseJPEGImageDecoder()
UsePNGImageDecoder()
UseTIFFImageDecoder()

Global dateiname.s
Global bild
Global t

dateiname = OpenFileRequester("Image auswählen...", "", "Image|*.bmp;*.jpg;*.png;*.tif", 0)

If dateiname <> ""
  bild = LoadImage(#PB_Any, dateiname)
 
  If bild
    t = ElapsedMilliseconds()
    hspiegeln(bild)
    t = ElapsedMilliseconds() - t
    MessageRequester("Info", "Horizontales spiegeln: " + Str(t) + "ms")
    SaveImage(bild, GetPathPart(dateiname) + "horizontal.bmp")
   
    hspiegeln(bild)
    t = ElapsedMilliseconds()
    vspiegeln(bild)
    t = ElapsedMilliseconds() - t
    MessageRequester("Info", "Vertikales spiegeln: " + Str(t) + "ms")
    SaveImage(bild, GetPathPart(dateiname) + "vertikal.bmp")
  EndIf
EndIf

End

Vielleicht kann es ja jemand gebrauchen. :wink:


Nach oben
 Profil  
Mit Zitat antworten  
 Betreff des Beitrags: Re: Image spiegeln
BeitragVerfasst: 21.09.2018 21:27 
Offline
Benutzeravatar

Registriert: 25.09.2016 01:42
Schön, danke für die Motivation :allright:
Hab mich auch mal an einer Version versucht um alle Images zu unterstützen.

Code:
Code:
... Entfernt verbuggt!



Viel Spass <)


Zuletzt geändert von Mijikai am 23.09.2018 11:13, insgesamt 1-mal geändert.

Nach oben
 Profil  
Mit Zitat antworten  
 Betreff des Beitrags: Re: Image spiegeln
BeitragVerfasst: 22.09.2018 20:41 
Offline

Registriert: 01.04.2011 21:59
:allright: Prima!

Eine Kleinigkeit: kann es sein, dass Du die Spiegelachsen vertauscht hast (Horizontal = 1 / Vertikal = 0)?

Ich habe mein vertikales Spiegeln unter dem Geschwindigkeitsaspekt noch mal bearbeitet. Die Funktion arbeitet jetzt in Abhängigkeit von der Farbtiefe nach der alten (schnellen) Methode bei 32 Bit oder mit CopyMemory() bei 24 Bit.
Da PB intern nur mit 24 oder 32 Bit Farbtiefe arbeitet, kann es nur 3 oder 4 Bytes pro Pixel geben. Bei 3 Bytes sind 2 x Poke() (einmal 2 Bytes + einmal 1 Byte) schneller als CopyMemory() für 3 Bytes. Ist nur ein marginaler Unterschied der selbst bei größeren Bildern nur einige Millisekunden ausmacht, aber immerhin. :wink:

Code:
Procedure vspiegeln(image)
  Protected zeilenlaenge                              ; Länge (in Byte) einer Zeile im Image
  Protected hoehe                                     ; Image-Höhe
  Protected breite                                    ; Image-Breite
  Protected tiefe                                     ; Farbtiefe des Images in Byte (echte Tiefe im Speicher)
  Protected *linkes.pixel                             ; Adresse des linken Pixels im Speicher
  Protected *rechtes.pixel                            ; Adresse des rechten Pixels im Speicher
  Protected i, j, k, l                                ; Laufvariablen
  Protected halbe_breite                              ; Image-Breite / 2 für optimierten Durchlauf
  Protected farbpuffer                                ; Zwischenspeicher für 1 Pixel bei 32Bit Farbtiefe
  Protected *pixelpuffer                              ; Zwischenspeicher ganzes Image bei 24Bit Farbtiefe
 
  ; Daten über das Image holen
  StartDrawing(ImageOutput(image))
    *linkes.pixel = DrawingBuffer()
    zeilenlaenge = DrawingBufferPitch()
  StopDrawing()
  hoehe = ImageHeight(image)
  breite = ImageWidth(image)
  tiefe = ImageDepth(image) / 8                       ; Bytes pro Pixel
  halbe_breite = breite / 2                           ; in eine Durchlauf linkes und rechtes Pixel tauschen, daher muss nur die halbe Länge durchlaufen werden
  l = ((breite - 1) * tiefe)                          ; Zeilenlänge in Pixel * Farbtiefe
 
  If tiefe = 4                                        ; "Paranoia-Abfrage" - Image sollte immer eine Tiefe von 32Bit haben!
    For i = 1 To hoehe
      k = zeilenlaenge                               
      *rechtes = *linkes + (tiefe * (breite-1))       ; Adresse des letzten Pixels in der Zeile
      For j = 1 To halbe_breite
        farbpuffer = *linkes\pix_l                    ; Farbe des linken Pixels merken
        *linkes\pix_l = *rechtes\pix_l                ; Farbe des rechten Pixels in linkes Pixel
        *rechtes\pix_l = farbpuffer                   ; Farbe des linken Pixels in rechtes Pixel
       
        *linkes + tiefe                               ; nächstes Pixel links
        *rechtes - tiefe                              ; nächstes Pixel rechts
        k - tiefe
      Next
      *linkes + k                                     ; Start der nächsten Zeile
    Next 
    ProcedureReturn -1
   
  ElseIf tiefe = 3
    *pixelpuffer = AllocateMemory(zeilenlaenge * hoehe)
    For i = 0 To hoehe-1
      k = i * zeilenlaenge
      For j = 0 To breite-1
;        CopyMemory(*linkes + k + (j * tiefe), *pixelpuffer + k + (l - j * tiefe), tiefe)
         PokeU(*pixelpuffer + k + (l - j * tiefe), PeekU(*linkes + k + (j * tiefe)))
         PokeA(*pixelpuffer + k + (l - j * tiefe) + 2, PeekA(*linkes + k + (j * tiefe) + 2))
      Next
    Next 
    CopyMemory(*pixelpuffer, *linkes, hoehe * zeilenlaenge)   
    FreeMemory(*pixelpuffer)
  Else
    Debug "VSpiegeln(): Farb-Tiefe muss 24 oder 32 Bit sein!"
  EndIf
EndProcedure


Nach oben
 Profil  
Mit Zitat antworten  
 Betreff des Beitrags: Re: Image spiegeln
BeitragVerfasst: 22.09.2018 21:25 
Offline

Registriert: 27.11.2016 18:13
Wohnort: Erzgebirge
Sieht gut aus und ist schnell.
Kann man gebrauchen. 8)

:allright:


Nach oben
 Profil  
Mit Zitat antworten  
 Betreff des Beitrags: Re: Image spiegeln
BeitragVerfasst: 11.11.2018 23:16 
Offline
Benutzeravatar

Registriert: 25.09.2016 01:42
Hier nochmal mein Code den ich vorübergehend wieder entfernt hatte da mir noch en Bug aufgefallen war.
Unterstützt alle PB (internen) Image - Formate.
Das Bild kann in alle Richtungen gespiegelt werden.

Viel Spaß :)

Code:
Code:
EnableExplicit

UsePNGImageDecoder()
UseJPEGImageDecoder()

Procedure.i FlipImage(Image.i,Flag.b = #Null);0 = Horizontal / 1 = Vertical / 2 = Horizontal & Vertical
  Protected Width.i
  Protected Height.i
  Protected *Buffer
  Protected BufferSize.i
  Protected *Source
  Protected Pitch.i
  Protected X.i
  Protected Y.i
  Protected Offset.i
  Protected PixelBytes.i
  Protected Result.i
  If IsImage(Image)
    Width = ImageWidth(Image)
    Height = ImageHeight(Image)
    PixelBytes = ImageDepth(Image,#PB_Image_InternalDepth) / 8
    If StartDrawing(ImageOutput(Image))
      Pitch = DrawingBufferPitch()
      BufferSize = Height * Pitch
      *Buffer = AllocateMemory(BufferSize)
      If *Buffer
        *Source = DrawingBuffer()
        Select Flag
          Case 1
            X = BufferSize - Pitch
            For Y = 0 To Height - 1
              Offset = Y * Pitch
              CopyMemory(*Source + Offset,*Buffer + X - Offset,Pitch)
            Next
          Case 2
            For Y = 0 To Height - 1
              Offset = Y * Pitch
              For X = 0 To Width - 1
                CopyMemory(*Source + Offset + (X * PixelBytes),*Buffer + Offset + ((Width - X) * PixelBytes),PixelBytes)
              Next
            Next
            CopyMemory(*Buffer,*Source,BufferSize)
            X = BufferSize - Pitch
            For Y = 0 To Height - 1
              Offset = Y * Pitch
              CopyMemory(*Source + Offset,*Buffer + X - Offset,Pitch)
            Next
          Default
            For Y = 0 To Height - 1
              Offset = Y * Pitch
              For X = 0 To Width - 1
                CopyMemory(*Source + Offset + (X * PixelBytes),*Buffer + Offset + ((Width - X) * PixelBytes),PixelBytes)
              Next
            Next
        EndSelect
        CopyMemory(*Buffer,*Source,BufferSize)
        Result = #True
        FreeMemory(*Buffer)
      EndIf
      StopDrawing()
    EndIf
  EndIf
  ProcedureReturn Result
EndProcedure

Global Image.i

Image = LoadImage(#PB_Any,"XYZ");<- BILD ÄNDERN!
If Image
  Debug FlipImage(Image,1)
  If OpenWindow(0,0,0,800,580,"",#PB_Window_ScreenCentered|#PB_Window_SystemMenu)
    If StartVectorDrawing(WindowVectorOutput(0))
      MovePathCursor(0,0)
      DrawVectorImage(ImageID(Image),$FF,800,580)
    EndIf
    Repeat
    Until WaitWindowEvent() = #PB_Event_CloseWindow
    CloseWindow(0)
  EndIf
  FreeImage(Image)
EndIf

End


Nach oben
 Profil  
Mit Zitat antworten  
 Betreff des Beitrags: Re: Image spiegeln
BeitragVerfasst: 11.11.2018 23:25 
Offline
Moderator
Benutzeravatar

Registriert: 05.10.2006 18:55
Wohnort: Rupture Farms
Danke auch für deinen Code, Mijikai, aber dein Code ist leider deutlich langsamer, als der von fabulouspaul.

_________________
BildBildBildBildBildBild


Nach oben
 Profil  
Mit Zitat antworten  
 Betreff des Beitrags: Re: Image spiegeln
BeitragVerfasst: 11.11.2018 23:40 
Offline
Benutzeravatar

Registriert: 25.09.2016 01:42
RSBasic hat geschrieben:
Danke auch für deinen Code, Mijikai, aber dein Code ist leider deutlich langsamer, als der von fabulouspaul.


:?
Vertikal ist mein Code etwas schneller & horizontal etwas langsamer.


Nach oben
 Profil  
Mit Zitat antworten  
Beiträge der letzten Zeit anzeigen:  Sortiere nach  
Ein neues Thema erstellen Auf das Thema antworten  [ 7 Beiträge ] 

Alle Zeiten sind UTC + 1 Stunde [ Sommerzeit ]


Wer ist online?

Mitglieder in diesem Forum: 0 Mitglieder und 1 Gast


Sie dürfen keine neuen Themen in diesem Forum erstellen.
Sie dürfen keine Antworten zu Themen in diesem Forum erstellen.
Sie dürfen Ihre Beiträge in diesem Forum nicht ändern.
Sie dürfen Ihre Beiträge in diesem Forum nicht löschen.

Suche nach:
Gehe zu:  

 


Powered by phpBB © 2008 phpBB Group | Deutsche Übersetzung durch phpBB.de
subSilver+ theme by Canver Software, sponsor Sanal Modifiye