Seite 1 von 1
XbpBitmap spiegeln?
Verfasst: So, 08. Jan 2017 14:55
von DelUser01
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?
Re: XbpBitmap spiegeln?
Verfasst: So, 08. Jan 2017 18:26
von ramses
Hallo Rolland
die FreeImage.dll hat dazu die Funktionen FlipHorizontal bezw. FlipVertikal
Cu Carlo
Re: XbpBitmap spiegeln?
Verfasst: So, 08. Jan 2017 20:56
von DelUser01
Hallo Carlo
danke für den Tip, ich werde es mit der freeimage.dll versuchen und melde mich wieder.
Re: XbpBitmap spiegeln?
Verfasst: Mo, 09. Jan 2017 1:46
von AUGE_OHR
"Mirror" und "Flip" sind "einfache" GDI Funktion mittels "PlgBlt"
https://msdn.microsoft.com/de-de/librar ... s.85).aspx
- API_Rotate.jpg (54.45 KiB) 8671 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) 207-mal heruntergeladen
p.s. mit "ROTATE.EXE /P" kann man den Performance Test verwenden.
Re: XbpBitmap spiegeln?
Verfasst: Mo, 09. Jan 2017 2:10
von DelUser01
Hallo Jimmy,
danke für die Info und das Demo!
Werde es nachher ausprobieren...
Re: XbpBitmap spiegeln?
Verfasst: Di, 10. Jan 2017 0:06
von DelUser01
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?
Re: XbpBitmap spiegeln?
Verfasst: Di, 10. Jan 2017 2:03
von AUGE_OHR
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.
Re: XbpBitmap spiegeln?
Verfasst: Di, 10. Jan 2017 2:18
von DelUser01
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...
Re: XbpBitmap spiegeln?
Verfasst: Di, 10. Jan 2017 22:28
von DelUser01
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 )
Re: XbpBitmap spiegeln?
Verfasst: Di, 10. Jan 2017 23:20
von DelUser01
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?
Re: XbpBitmap spiegeln?
Verfasst: Di, 10. Jan 2017 23:34
von AUGE_OHR
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 ...
---
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
stehen um dort das aktuelle oBitmap zu "malen"
du kannst jederzeit ein neues Bitmap "setzen" mit
und um die Änderrung "sichtbar" zu machen folgt ein
damit wird dann der o:
Paint Codeblock Slot ausgelöst welcher dann das "malen" übernimmt.
Re: XbpBitmap spiegeln?
Verfasst: Mi, 11. Jan 2017 1:01
von DelUser01
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.
Re: XbpBitmap spiegeln?
Verfasst: Mi, 11. Jan 2017 8:29
von ramses
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
Re: XbpBitmap spiegeln?
Verfasst: Mi, 11. Jan 2017 13:58
von DelUser01
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!
Re: XbpBitmap spiegeln?
Verfasst: Do, 12. Jan 2017 8:45
von AUGE_OHR
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 ...
Anmerkung : was ich im "DC" habe ist noch längst nicht im Presspace obwohl ich es "sehe"
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
Re: XbpBitmap spiegeln?
Verfasst: Mo, 16. Jan 2017 6:29
von DelUser01
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!
Re: XbpBitmap spiegeln?
Verfasst: Di, 17. Jan 2017 8:59
von ramses
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
Re: XbpBitmap spiegeln?
Verfasst: Di, 17. Jan 2017 9:36
von brandelh
Der Link geht in den Mitgliederbereich ... nur der Autor darf entscheiden ob er den Inhalt außerhalb veröffentlichen will.
Re: XbpBitmap spiegeln?
Verfasst: Di, 17. Jan 2017 9:53
von ramses
@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
Re: XbpBitmap spiegeln?
Verfasst: Di, 17. Jan 2017 9:55
von Martin Altmann
Moin Carlo,
genau - Mitglieder im Verein Deutschsprachige Xbase-Entwickler e. V.
Viele Grüße,
Martin