Das Forentreffen 2018 findet am 20./21. April in Dresden statt. Weitere Infos hier
Anmeldungen zum Forentreffen 2018 sind auf der Anmeldeseite möglich
Zur Homepage des Deutschsprachige Xbase-Entwickler e. V.
Xbase++-Wiki des Deutschsprachige Xbase-Entwickler e. V.

XbpBitmap spiegeln?

Grafische Primitive, XbaseParts und Darstellungsfragen allgemein.

Moderator: Moderatoren

Antworten
Benutzeravatar
Roland Gentner
1000 working lines a day
1000 working lines a day
Beiträge: 954
Registriert: Fr, 24. Nov 2006 8:30
Wohnort: Neresheim
Kontaktdaten:

XbpBitmap spiegeln?

Beitrag von Roland Gentner » So, 08. Jan 2017 14:55

Hallo

suche eine schnellere Möglichkeit ein XbpBitmap zu spiegeln.
Meine eingebaute Variante ist inzwischen viel zu langsam. Ich benutze bisher GetPixel() und SetPixelV()

Code: Alles auswählen

aDestSize := CenterAndFitBitmap(...)
oBitmap:Draw( oPS , aDestSize , , , GRA_BLT_BBO_IGNORE )
nHWnd := oDrawingArea:GetHWnd()
nHDC  := GetDC( nHWnd )
nLine := aDestSize[3] - aDestSize[1]
aLine := Array( nLine )
nRows := aDestSize[4] - aDestSize[2]
For nCnt2 := 1 To nRows
   For nCnt1 := 1 To nLine
      aLine[nCnt1] := GetPixel( nHDC , ( nCnt1 - 1 ) + aDestSize[1] , ( nCnt2 - 1 ) + aDestSize[2] )
   Next nCnt1
   nCol1 := nLine + 1
   For nCnt1 := 1 To nLine
      nCol1--
      SetPixelV( nHDC , nCol1 + aDestSize[1] , ( nCnt2 - 1 ) + aDestSize[2] , aLine[nCnt1] )
    Next nCnt1
 Next nCnt2
Vermutlich wäre es auch schneller wenn das Get + Set nicht "live" am Screen passieren würde sondern verdeckt. Und dann auf einen Sitz die geänderte Grafik angezeigen.
Es gibt ein älteres Thema dazu - hat mir aber auch nicht richtig weitergeholfen:
http://www.xbaseforum.de/viewtopic.php? ... p+spiegeln

Hätte da jemand eine bessere Lösung?
Gruß
Roland

ramses
1000 working lines a day
1000 working lines a day
Beiträge: 760
Registriert: Mi, 28. Jul 2010 17:16

Re: XbpBitmap spiegeln?

Beitrag von ramses » So, 08. Jan 2017 18:26

Hallo Rolland

die FreeImage.dll hat dazu die Funktionen FlipHorizontal bezw. FlipVertikal


Cu Carlo

Benutzeravatar
Roland Gentner
1000 working lines a day
1000 working lines a day
Beiträge: 954
Registriert: Fr, 24. Nov 2006 8:30
Wohnort: Neresheim
Kontaktdaten:

Re: XbpBitmap spiegeln?

Beitrag von Roland Gentner » So, 08. Jan 2017 20:56

Hallo Carlo

danke für den Tip, ich werde es mit der freeimage.dll versuchen und melde mich wieder.
Gruß
Roland

Benutzeravatar
AUGE_OHR
Marvin
Marvin
Beiträge: 10731
Registriert: Do, 16. Mär 2006 7:55
Wohnort: Hamburg

Re: XbpBitmap spiegeln?

Beitrag von AUGE_OHR » Mo, 09. Jan 2017 1:46

"Mirror" und "Flip" sind "einfache" GDI Funktion mittels "PlgBlt"
https://msdn.microsoft.com/de-de/librar ... s.85).aspx
API_Rotate.jpg
API_Rotate.jpg (54.45 KiB) 912 mal betrachtet

Code: Alles auswählen

METHOD RotateDlg:DrawMirror()
LOCAL oSource   := ::oStatic1              // das ist die linke Static mit dem Bild
LOCAL aPos1     := {0,0}
LOCAL aSize1    := ::oStatic1:CurrentSize()
LOCAL oDest     := ::oStatic2               // das ist die leere rechte Static als Ziel
LOCAL aPos2     := {0,0}
LOCAL nRet
LOCAL aVertices := {}
LOCAL cVertices

   aPos1[1] := (::aOrgMove[1])
   aPos1[2] := (::aOrgMove[2])

   aVertices := {{aPos1[1]+aSize1[1],aPos1[2]+aSize1[2]},;
                 {aPos1[1]          ,aPos1[2]+aSize1[2]},;
                 {aPos1[1]+aSize1[1],aPos1[2]          }}

   cVertices := L2Bin(aVertices[1,1])+L2Bin(oDest:CurrentSize()[2]-aVertices[1,2])+;
                L2Bin(aVertices[2,1])+L2Bin(oDest:CurrentSize()[2]-aVertices[2,2])+;
                L2Bin(aVertices[3,1])+L2Bin(oDest:CurrentSize()[2]-aVertices[3,2])

   nRet := PlgBlt(::hDC2              ,;   // Handle Ziel
                  cVertices           ,;
                  ::hDC1              ,;   // Handle Source
                  aPos2[1],  aPos2[2] ,;
                 aSize1[1], aSize1[2] ,;
                  0, 0, 0)

RETURN nRet

* --------------------------------------------------------------- *

#command  GDIFUNCTION <Func>([<x,...>]) ;
       => ;
FUNCTION <Func>([<x>]);;
STATIC scHCall := nil ;;
   IF scHCall == nil ;;
      IF snHdll == nil ;;
         snHDll := DllLoad('GDI32.DLL') ;;
      ENDIF ;;
      scHCall := DllPrepareCall(snHDll,DLL_STDCALL,<(Func)>) ;;
   ENDIF ;;
RETURN DllExecuteCall(scHCall,<x>)

GDIFUNCTION PlgBlt(hdcDest,lpPoint,hdcSrc,nXSrc,nYSrc,nWidth,nHeight,hbmMask,xMask,yMask)
ROTATE.ZIP
EXE v1.9x
(51 KiB) 19-mal heruntergeladen
p.s. mit "ROTATE.EXE /P" kann man den Performance Test verwenden.
Zuletzt geändert von AUGE_OHR am Di, 10. Jan 2017 2:17, insgesamt 1-mal geändert.
gruss by OHR
Jimmy

Benutzeravatar
Roland Gentner
1000 working lines a day
1000 working lines a day
Beiträge: 954
Registriert: Fr, 24. Nov 2006 8:30
Wohnort: Neresheim
Kontaktdaten:

Re: XbpBitmap spiegeln?

Beitrag von Roland Gentner » Mo, 09. Jan 2017 2:10

Hallo Jimmy,

danke für die Info und das Demo!
Werde es nachher ausprobieren...
Gruß
Roland

Benutzeravatar
Roland Gentner
1000 working lines a day
1000 working lines a day
Beiträge: 954
Registriert: Fr, 24. Nov 2006 8:30
Wohnort: Neresheim
Kontaktdaten:

Re: XbpBitmap spiegeln?

Beitrag von Roland Gentner » Di, 10. Jan 2017 0:06

Hallo Jimmy,

leider funktioniert rotate.exe nicht mit der aktuellen Xbase Version 2 es wird 1.9x benötigt.
Aber es geht nicht darum dass Dein EXE läuft - ich glaube Dir dass das funktionirt. Dein Source-Schnipsel ist wichtiger.
Die Funktion PlgBlt hatte ich bei MSDN schon nachgelesen, die Einstzmöglichkeiten aber nicht begriffen. Im Augenblick liegt das Thema auf den Stapel "böhmische Dörfer".

Was ich sehe ist, dass ich von einem Objekt (dem ersten) in ein Zweites wandle.
Ich weiß noch nicht einmal um was für Objekte es sich handelt. oXbpBitmap, oPresentationSpace, ...
Wenn es sich um einen zweiten PS handelt wie erstelle ich den und wie wird der nachher zum ersten PS usw.

Befinde mich bei der grafischen Oberfläche noch im "Eingangsbereich". Bin eben ein Programmierer von Verwaltungssystemen.
Werde mich noch einige Zeit lang damit beschäftigen müssen um die Sache zu begreifen...

Oder kannst Du mir das so aufbereiten dass ich das als Funktion nur einbinden muss?
Inklusive Source? Preis?
Gruß
Roland

Benutzeravatar
AUGE_OHR
Marvin
Marvin
Beiträge: 10731
Registriert: Do, 16. Mär 2006 7:55
Wohnort: Hamburg

Re: XbpBitmap spiegeln?

Beitrag von AUGE_OHR » Di, 10. Jan 2017 2:03

Roland Gentner hat geschrieben:Oder kannst Du mir das so aufbereiten dass ich das als Funktion nur einbinden muss?
da ist nun nichts "geheimes" an meinem Code

Code: Alles auswählen

   ::oStatic1 := XbpStatic():new( ::drawingArea, , {24,120}, {225,225}, { { XBP_PP_BGCLR, -255 } } )
   ::oStatic1:clipSiblings := .T.

   ::oStatic2 := XbpStatic():new( ::drawingArea, , {336,120}, {225,225}, { { XBP_PP_BGCLR, -255 } } )
   ::oStatic2:clipSiblings := .T.

   ::oStatic1:type := XBPSTATIC_TYPE_BITMAP
   ::oStatic2:type := XBPSTATIC_TYPE_BITMAP
also 2 Static als Parent für das Bitmap (BMP,JPG,PNG,GIF)
zu beachten {{XBP_PP_BGCLR, -255}} wenn man ein Bitmap mit Transparenz hat.

Code: Alles auswählen

   oPS := ::oStatic1:lockPS()
   ::oBitmap := ResourceAsBmp():New():create( oPS )
   ::oBitmap:load(AppName(),2000,"JPG")
   ::oStatic1:unlockPS(oPS)
   ::oStatic1:SetCaption(::oBitmap)

*  ::oStatic2:SetCaption(::oBitmap)

   ::hDC1  := GetWindowDC( ::oStatic1:GetHWnd() )
   ::hDC2  := GetWindowDC( ::oStatic2:GetHWnd() )
nun lade ich das Bitmap, hier aus einer Resource Datei, und verwende o:SetCaption()
warum ich jeweils einen Parent benötige hat mit der API Function GetWindowDC() zu tun.

Anmerkung : wir Xbase++ User "malen" in den Pressspace ... Windows in den "DC" (Device Context)

in der METHOD RotateDlg:DrawMirror() findet man noch

Code: Alles auswählen

   aPos1[1] := (::aOrgMove[1])
   aPos1[2] := (::aOrgMove[2])
was hier her kommt

Code: Alles auswählen

   ::aOrgMove := { (::nOutCirle-aSize1[1])/2 ,;
                   (::nOutCirle-aSize1[2])/2 }
die Koordinaten sind das Centrum von einem Kreis.

das ganze ist für einen Vergleich API GetPixel()/SetPixel() vs. PlgBlt()
es "dreht" in diesem Demo die Pixel -> Rotate

Code: Alles auswählen

   PlgBlt(::hDC2              ,;  // Target (Ziel)
          cVertices           ,;  // das bestimmt was passiert
          ::hDC1              ,;  // Source
          ... 
das selbe geht nur für "Mirror" (Horizontal) und "Flip" (Vertikal)

mit GetWindowDC() habe ich das Handle vom Fenster "DC" bekommen.
die API PlgBlt() nimmt also nicht einzelne Pixel sondern den ganzen Fenster "Inhalt".

die "Transformation" von dem Kreis is ja nur 2D.
man kann die Vertrix Matrix auch so aufbauen das die zu einem Fluchpunkt laufen -> angedeutetes 3D

ich werde den Source zu Demo in den Mitglieder Bereich uploaden.
gruss by OHR
Jimmy

Benutzeravatar
Roland Gentner
1000 working lines a day
1000 working lines a day
Beiträge: 954
Registriert: Fr, 24. Nov 2006 8:30
Wohnort: Neresheim
Kontaktdaten:

Re: XbpBitmap spiegeln?

Beitrag von Roland Gentner » Di, 10. Jan 2017 2:18

Hallo Jimmy

Danke für die schnelle Antwort!
Scheinst ja auch ein Nachtarbeiter zu seín.
Schaue mir die Sache nachher genauer an. Jetzt ist erst einmal Feierabend. Habe die letzten Tage wenig geschlafen...
Gruß
Roland

Benutzeravatar
Roland Gentner
1000 working lines a day
1000 working lines a day
Beiträge: 954
Registriert: Fr, 24. Nov 2006 8:30
Wohnort: Neresheim
Kontaktdaten:

Re: XbpBitmap spiegeln?

Beitrag von Roland Gentner » Di, 10. Jan 2017 22:28

Hallo Jimmy

wie gesagt - bei den Objekten bin ich Laie.
Ich benutze kein XbpStatic, ich verwende den Presentation Space. Dann bräuchte ich also einen zweiten PS (oPS2). Nach dem Spiegeln von oPS1 zu oPS2 müsste ich dann die zwei PS austauschen - oder?

das Dialog-Fenster:
- oDialog:XbpDialog():New(...)
- oDialog:DrawingArea:Paint := { | aRect , uNIL , oDrawingArea | GsPViewerPaint( aRect , oDrawingArea ) }
ich lade das Bild mit:
- oBitmap := XbpBitmap():New():Create()
- oBitmap:LoadFile( cBildFile )
anzeigen:
- oPS1 := oDrawingArea:LockPS()
- oBitmap:Draw( oPS1 , aDestSize , , , GRA_BLT_BBO_IGNORE )
Gruß
Roland

Benutzeravatar
Roland Gentner
1000 working lines a day
1000 working lines a day
Beiträge: 954
Registriert: Fr, 24. Nov 2006 8:30
Wohnort: Neresheim
Kontaktdaten:

Re: XbpBitmap spiegeln?

Beitrag von Roland Gentner » Di, 10. Jan 2017 23:20

Hallo Jimmy

wenn ich das richtig sehe wird mit PlgBlt() in diesem Beispiel die jeweils gesamte Drawing Area gespiegelt, nicht nur das Bitmap - oder?

Ich brauche also eine zweite DrawingArea und kein zweites Bitmap - oder?
Gruß
Roland

Benutzeravatar
AUGE_OHR
Marvin
Marvin
Beiträge: 10731
Registriert: Do, 16. Mär 2006 7:55
Wohnort: Hamburg

Re: XbpBitmap spiegeln?

Beitrag von AUGE_OHR » Di, 10. Jan 2017 23:34

hi,

wann soll denn das Bild "spiegeln" passieren ?

ich "denke" nach dem laden des Original, was dann gespiegelt werden soll ( warum nicht gleich im Original ? )
die 2 x Fenster Handle benötige ich ja für die API Function PlgBlt() wobei es "sichtbar" sein soll.
ob die Fenster "sichtbar" sein müssen ... :-k
---
ich "lese" den "Inhalt" eines Fenster und übertrage es in den "Inhalt" eines anderen Fenster.
ich bin mir relative sicher das ich den "Inhalt" des 2nd Fenster "abspeichern" kann zur weiteren Verarbeitung.
---
in dem Rotate Demo habe das Handle (o:GetHwnd() ) der Static für die API Function GetWindowDC() genommen um einen "DC" zu bekommen.
bei ein "DC" (Device Context) "hängt" aber was dran. man kann aber auch eine "MemoryDC" kreieren.

Code: Alles auswählen

FUNCTION CreateMemoryDC( hDC, nXSize, nYSize )
LOCAL hMemoryDC, hBMP

   hMemoryDC := CreateCompatibleDC(hDC)    // create compatible memory DC
   hBMP      := CreateCompatibleBitmap(hDC,nXSize,nYSize) // create DDB
   SelectObject(hMemoryDC,hBMP)                    // put hBMP into memory DC
   BitBlt( hMemoryDC,0,0,nXSize,nYSize,hDC,0,0,SRCCOPY ) // copy desktop DC into memory DC

RETURN hMemoryDC
das geht natürlich jetzt tiefer in die Bitmap Manipulation.

wer sich mehr mit der Materie beschäfigen will sollte sich FreeImage.DLL ansehen
für die Pablo einen Xbase++ Wrapper (imagefree.rar) mit ot4xb geschrieben hat.

dein

Code: Alles auswählen

 oDialog:DrawingArea:Paint := { | aRect , uNIL , oDrawingArea | GsPViewerPaint( aRect , oDrawingArea ) }
sorgt ja dafür das änderungen durch die Function GsPViewerPaint() "behandelt" werden.

Code: Alles auswählen

   oPS1 := oDrawingArea:LockPS()
   oBitmap:Draw( oPS1 , aDestSize , , , GRA_BLT_BBO_IGNORE )
das sollte in deiner Function

Code: Alles auswählen

GsPViewerPaint(oBitmap,aRect,oDrawingArea) 
stehen um dort das aktuelle oBitmap zu "malen"

du kannst jederzeit ein neues Bitmap "setzen" mit

Code: Alles auswählen

   oDialog:DrawingArea:Bitmap := oBitmap
und um die Änderrung "sichtbar" zu machen folgt ein

Code: Alles auswählen

   oDialog:DrawingArea:invalidateRect()
damit wird dann der o:Paint Codeblock Slot ausgelöst welcher dann das "malen" übernimmt.
gruss by OHR
Jimmy

Benutzeravatar
Roland Gentner
1000 working lines a day
1000 working lines a day
Beiträge: 954
Registriert: Fr, 24. Nov 2006 8:30
Wohnort: Neresheim
Kontaktdaten:

Re: XbpBitmap spiegeln?

Beitrag von Roland Gentner » Mi, 11. Jan 2017 1:01

Hallo Jimmy

Deine Erläuterungen habe ich soweit verstanden. Auch die Vorgehensweise und (ein Teil) der Aufbereitung für PlgBlt.
...was für ein Aufwand um in heutiger Zeit ein Bitmap zu spiegeln.
Habe zu viel Zeit mit dieser "vermeintlich" einfachen Aufgabe verbracht und breche das an dieser Stelle ab.

Noch zu Deiner Frage wann das Bitmap gespiegelt werden soll:
am besten bereits beim Laden von der Disk. Es sollen alle gespiegelt dargestellt werden.
(Die Original-Datei auf der HDD darf dabei in keiner Weise geändert/aktualisiert werden)

Danke für Deine Hilfe - werde irgendwann daran weitermachen.
Gruß
Roland

ramses
1000 working lines a day
1000 working lines a day
Beiträge: 760
Registriert: Mi, 28. Jul 2010 17:16

Re: XbpBitmap spiegeln?

Beitrag von ramses » Mi, 11. Jan 2017 8:29

Hallo Roland

dein Problem kannst du auf dem "Quick and Dirty Way" einfach und sehr sehr schnell lösen.
Spiegle doch deine Original-BMP-Datei zuerst in ein Temporäres Verzeichnis und nimm danach diese gespiegelte Datei zur Anzeige.
Mit der Free_Image.dll geht dies sehr schnell und einfach mit wenigen Zeilen:

Code: Alles auswählen

function flip_bmp_hor()
local nDll
local cFnameSrc := "1988.bmp"      // Originaldatei 
local cFnameTMP := "e:\2988.bmp"   // TMP Datei auf Ramdisk 

   FreeImage_Initialise(.t.)
   nDll := freeImage_Load( FREE_IMAGE_FORMAT.FIF_BMP, cFnameSrc, BMP_DEFAULT )
   freeImage_FlipHorizontal( nDLL )
   freeImage_Save(FREE_IMAGE_FORMAT.FIF_BMP, nDll, cFnameTMP, BMP_DEFAULT )
   freeImage_Unload( nDll )
   FreeImage_DeInitialize( )

   return(nil)


Melde dich wenn du weitere Infos / Code benötigst.

Cu Carlo

Benutzeravatar
Roland Gentner
1000 working lines a day
1000 working lines a day
Beiträge: 954
Registriert: Fr, 24. Nov 2006 8:30
Wohnort: Neresheim
Kontaktdaten:

Re: XbpBitmap spiegeln?

Beitrag von Roland Gentner » Mi, 11. Jan 2017 13:58

Hallo Carlo

so oder ähnlich hatte ich mir das mit einem Programm eines Drittanbieters auch scho gedacht.

Danke für den Code - werde es probieren!
Gruß
Roland

Benutzeravatar
AUGE_OHR
Marvin
Marvin
Beiträge: 10731
Registriert: Do, 16. Mär 2006 7:55
Wohnort: Hamburg

Re: XbpBitmap spiegeln?

Beitrag von AUGE_OHR » Do, 12. Jan 2017 8:45

ich habe mal weiter mit der API PlgBlt() getestet :

a.) Source Fenster kann auch = Ziel Fenster sein.
b.) man kann das Bitmap abspeichern (MIRROR.BMP)

allerdings funktioniert es nur wenn das Source Fenster sichtbar ist.

es gibt jedoch wieder eine Xbase++ "Eigenart" :
ich muss es erst in ein neues XbpBitmap() per GraBitBlt() bringen ... :evil:

Anmerkung : was ich im "DC" habe ist noch längst nicht im Presspace obwohl ich es "sehe" #-o

so geht nun die Function

Code: Alles auswählen

   oBitmap := FlipImage(oStatic,.T.) // .T. = vertikal / .F. = horizontal
   oStatic:Setcaption(oBitmap)
die Static hat als Caption das (Original) Image
geht auch mit der o:DrawingArea als Parameter wenn es ein Bild hat (o:DrawingArea:Bitmap)

anbei EXE v1.9x, Source im Mitgliederbereich
p.s. als Parameter ein Bitmap (BMP, JPG, PNG,GIF) angeben. es wird die Datei MIRROR.BMP erzeugt
Dateianhänge
MIRROR_EXE.ZIP
Xbase++ v1.9.355
(10.76 KiB) 16-mal heruntergeladen
gruss by OHR
Jimmy

Benutzeravatar
Roland Gentner
1000 working lines a day
1000 working lines a day
Beiträge: 954
Registriert: Fr, 24. Nov 2006 8:30
Wohnort: Neresheim
Kontaktdaten:

Re: XbpBitmap spiegeln?

Beitrag von Roland Gentner » Mo, 16. Jan 2017 6:29

Hallo Carlo

die Variante mit der FreeImage.dll habe ich ausprobiert - hat funktioniert.
Mache das jetzt aber ohne FreeImage.dll - habe das Beispiel von Jimmy zum Laufen gebracht:
http://www.xbaseforum.de/viewtopic.php?f=62&t=9570

Danke!
Gruß
Roland

ramses
1000 working lines a day
1000 working lines a day
Beiträge: 760
Registriert: Mi, 28. Jul 2010 17:16

Re: XbpBitmap spiegeln?

Beitrag von ramses » Di, 17. Jan 2017 8:59

Hallo Roland

schön dass es läuft.

Wo hast du dein Beispiel hingesetzt:

Ich bekomme nur:
Du hast keine Berechtigung, dieses Forum zu lesen.

Cu Carlo

Benutzeravatar
brandelh
Foren-Moderator
Foren-Moderator
Beiträge: 13903
Registriert: Mo, 23. Jan 2006 20:54
Wohnort: Germersheim
Kontaktdaten:

Re: XbpBitmap spiegeln?

Beitrag von brandelh » Di, 17. Jan 2017 9:36

Der Link geht in den Mitgliederbereich ... nur der Autor darf entscheiden ob er den Inhalt außerhalb veröffentlichen will.
Gruß
Hubert

ramses
1000 working lines a day
1000 working lines a day
Beiträge: 760
Registriert: Mi, 28. Jul 2010 17:16

Re: XbpBitmap spiegeln?

Beitrag von ramses » Di, 17. Jan 2017 9:53

@Hubert

Danke für die Erklährung. Ich nehme an mit "Mitglieder" sind "Vereinsmitglieder" gemeint. Das bin ich nicht. Es ist richtig "der Author entscheidet"

Cu Carlo

Benutzeravatar
Martin Altmann
Foren-Administrator
Foren-Administrator
Beiträge: 13807
Registriert: Fr, 23. Sep 2005 4:58
Wohnort: Berlin
Kontaktdaten:

Re: XbpBitmap spiegeln?

Beitrag von Martin Altmann » Di, 17. Jan 2017 9:55

Moin Carlo,
genau - Mitglieder im Verein Deutschsprachige Xbase-Entwickler e. V.

Viele Grüße,
Martin
:grommit:
Webseite mit XB2.NET und ausschließlich statischem Content in Form von HTML-Dateien: http://www.altem.de/
Webseite mit XB2.NET und ausschließlich dynamischem Content in Form von in-memory-HTML: http://meldungen.altem.de/

Mitglied der XUG Osnabrück
stellv. Vorsitzender des Deutschsprachige Xbase-Entwickler e. V.

Antworten