![]() |
Bitmap als Pointer auf einem Display ausgeben
Hallo,
bin gerade dabei an einer Ansteuerung eines Displays zu arbeiten und benötige eventuell noch ein wenig Hilfe bei der richtigen Umsetzung. Die Dll zur Ansteuerung des Displays besitzt eine Funktion mit der man ein "Bitmap" direkt übertragen kann. Das Bitmap muss vom Typ Pointer.
Delphi-Quellcode:
Habe dann überall gesucht und bin dann auf etwas gestossen, was mit das Bitmap in einen Pointer setzt.
Function LUI_Bitmap(DevNum: Integer; ScreenNr: Byte; ScreenPosX: Integer; ScreenPosY: Integer;
BMPoffsetX: Integer; BMPoffsetY: Integer; BMPWidth: Integer; BMPHigh: Integer; BMPdataWidth: Integer; BMPdataHigh: Integer; Bitmap: Pointer): Byte; StdCall; External 'LUIse.dll'
Delphi-Quellcode:
Die Funktion leistet auch wunderbare Dienste. Einzieger Nachteil ist es ist Vertikal gespiegelt. Das ist natürlich nicht gewollt!
procedure TDisplay.BMPtoPointer(Bitmap: TBitmap);
var Info : PBitmapInfo; InfoSize : DWord; Image : Pointer; ImageSize : DWord; begin with Bitmap do begin GetDIBSizes(Handle, InfoSize, ImageSize); Info := AllocMem(InfoSize); try Image := AllocMem(ImageSize); try GetDIB(Handle, Palette, Info^, Image^); { Bild an das Display übergeben } _Bitmap(0, 0, 30, 120, 0, 0, Width, Height, 320, 240, Image); // umsetung von LUI_Bitmap finally FreeMem(Image, ImageSize); end; finally FreeMem(Info, InfoSize); end; end; end; Habe es dann vor der Ausgabe auf das Display vertikal gespeigelt.
Delphi-Quellcode:
Damit habe ich nun auf dem Display mein Bild so wie es sein soll.
PROCEDURE TDisplay.Spiegeln(VAR Bitmap: TBitmap);
BEGIN Bitmap.Canvas.CopyRect(Rect(0,Bitmap.Height-1, Bitmap.Width,-1), Bitmap.Canvas, Rect(0,0, Bitmap.Width,Bitmap.Height)); END;
Delphi-Quellcode:
Diese Funktion wird z.Z. alle 50ms aufgerufen, da sie das Audiospectrum wieder gibt.
Spiegeln(VisBuff);
BMPtoPointer(VisBuff); Frage ist nun ob man das so lassen kann oder ob es dafür vllt. noch eine bessere und schnellere Methode gibt. Es ist für mich das erste mal das ich mit sowas arbeite also entschuldigt falls das nicht so die korrekte Umsetzung ist aber sie funktioniert z.Z. Dies ist ja auch er Grund warum ich den Thread jetzt schreibe. Gruss Cyberaxx |
Re: Bitmap als Pointer auf einem Display ausgeben
Ich bin mir gerade nicht ganz sicher, aber ist das interne Format in 'nem TBitMap nicht eh schon DIB?
Also wenn das so ist, könnte man sich ja eventuell den Pointer darauf besorgen und somit ein bissl Zeit sparren ... im Moment wird ja ein neues Bild (in Variable Image) erstlle und freigegeben. Mir war auch schon der gedanke gekommen, daß man auf die INFO verzichten könnte, aber ich glaub mal nicht, daß es hier geht -.-'' Also etwa so?
Delphi-Quellcode:
PS: falls du Lust hast ... es geht auch kürzer (mußt nicht jedesmal INTEGER einzeln angeben) ^_^
procedure TDisplay.BMPtoPointer(Bitmap: TBitmap);
var Image : Pointer; ImageSize : DWord; begin with Bitmap do begin GetDIBSizes(Handle, InfoSize, ImageSize); Image := AllocMem(ImageSize); try GetDIB(Handle, Palette, nil, Image^); { Bild an das Display übergeben } _Bitmap(0, 0, 30, 120, 0, 0, Width, Height, 320, 240, Image); // umsetung von LUI_Bitmap finally FreeMem(Image, ImageSize); end; end; end;
Delphi-Quellcode:
Function LUI_Bitmap(DevNum: Integer; ScreenNr: Byte; ScreenPosX, ScreenPosY,
BMPoffsetX, BMPoffsetY, BMPWidth, BMPHigh, BMPdataWidth, BMPdataHigh: Integer; Bitmap: Pointer): Byte; StdCall; External 'LUIse.dll'; |
Re: Bitmap als Pointer auf einem Display ausgeben
Guten Morgen,
das will leider nicht so... :D
Delphi-Quellcode:
Da fehlt das InoSize, habs hinzugefügt aber er braucht doch die Info :(
var
Image : Pointer; ImageSize : DWord; begin with Bitmap do begin GetDIBSizes(Handle, InfoSize, ImageSize);
Delphi-Quellcode:
GetDIB(Handle, Palette, nil, Image^);
[Fehler] LUI.pas(173): Konstantenobjekt kann nicht als Var-Parameter weitergegeben werden |
Re: Bitmap als Pointer auf einem Display ausgeben
Habsch mir fast schon gedacht ... bei vielen WinAPI-Funktionen funktioniert sowas ja, aber in Delphi halt nicht unbedingt -.-''
Ansonsten bleibt halt noch mein erster Vorschlag ... wenn intern wirklich DIB, dann direkt daruf zugreifen, ansonsten scheint's ja keinen anderen Weg zu geben. |
Re: Bitmap als Pointer auf einem Display ausgeben
Wenn Du mir kurz helfen würdest damit ich weiss wie ich drauf zugreifen sollte.
Ist ja das erste mal das ich damit arbeite... :( |
Re: Bitmap als Pointer auf einem Display ausgeben
Leider habe ich so tief im TBitMap auch noch nicht rumgestöbert, mir ist nur so, als wenn ich mal was gelesen hatte, das TBitMap intern oftmals auch mit DIB's arbeitet (bzw. daß man ihm sagen kann, womit es arbeiten soll), demnach sollte es ja eine Möglichkeit geben auch direkt darauf zuzugreifen.
(hab im Moment auch nur mein D4 hier und kann demanch nicht ma schnell in den Quellcodes nachsehn, was z.B. die Funktion GetDIB intern macht) |
Re: Bitmap als Pointer auf einem Display ausgeben
Hi,
ja, den richtigen Datentyp zu finden ist etwas komplizierter, du brauchst nämlich eine Variable vom Typ BitmapInfo (gehört zu GDI und damit zur Unit Windows). Eine Bitmap unter Windows ist eigentlich nur eine Matrix von Pixeldaten. Alles zusätzliche speichert Windows getrennt in einem zur Bitmap gehörenden BitmapInfo (Breite, Höhe, Pixelformat, ...). Delphi kapselt einfach nur beides in dem so genannten TBitmap Objekt. Damit deine Funktion funktioniert, musst du eine Variable vom Typ BitmapInfo anlegen (ok, hatten wir schon), genau so wichtig ist es aber, dass du deinen Zeiger Image nicht unitialisiert übergibst. Der muss auf ein Feld zeigen, dass groß genug ist um alle Pixelinfos der Bitmap aufzunehmen (also Width * Height * PixelFormat in Byte). Gruß Der Unwissende |
Re: Bitmap als Pointer auf einem Display ausgeben
Soeben beim ändern der Bitmapgrösse wird das bitmap nicht mehr richtig dargestellt. ändere ich manuell den Wert des BMPdataWidth wird das Bild wieder richtig dargestellt. Je nach Grösse des Bitmaps ändert sich auch der Wert der zu BMPdatawidth addiert werden muss.
Hab mal grob rumgespielt. Wenn das Bitmap ne Breite von 200 hat liegt der Wert ca. bei 224. Ist das Bitmap 100 Breit liegt der Wert bei ca. 130. Hier mal der Auszug aus der Dokumentation:
Code:
LUI_Bitmap
Beschreibung: Lädt die übergebenen Bild-Daten in den entsprechenden Grafik-Screen. Syntax: ErrorCode LUI_Bitmap (int DevNum, unsigned char ScreenNr, int ScreenPosX, int ScreenPosY, int BMPoffsetX, int BMPoffsetY, int BMPWidth, int BMPHight, int BMPdataWidth, int BMPdataHight, unsigned char *Bitmap)
Code:
Könnte mir jemand helfen, was es mit dem Wert auf sich hat?
Parameter:
DevNum: Index des Gerätes (0…3) ScreenNr: Grafik-Screennummer (0,1) ScreenPosX: X-Koordinate der linken oberen Ecke des auszugebenden Bitmaps auf dem LCD ScreenPosY: Y-Koordinate der linken oberen Ecke des auszugebenden Bitmaps auf dem LCD BMPoffsetX: X-Offset der linken oberen Ecke des auszugebenden Bitmaps innerhalb der Bitmap-Daten (z.B. um nur einen Teilbereich eines Bitmaps auf dem LCD auszugeben) BMPoffsetY: Y-Offset der linken oberen Ecke des auszugebenden Bitmaps innerhalb der Bitmap-Daten (z.B. um nur einen Teilbereich eines Bitmaps auf dem LCD auszugeben) BMPWidth: Breite des auszugebenden Bitmaps BMPHight: Höhe des auszugebenden Bitmaps BMPdataWidth: Breite der gesamten Bitmap-Daten in Pixel BMPdataHight: Höhe der gesamten Bitmap-Daten in Pixel Bitmap: Zeiger auf Array mit Bitmap-Daten Beispiel: unsigned char ErrorCode; int DevNum=0; unsigned char BMPData[9600]; //BMPData[9600] mit Bitmapdaten laden (schwarz/weiß), z.B. Hintergrundbild 320x240 //… ErrorCode = LUI_Bitmap (DevNum, 0, 0, 0, 0, 0, 320, 240, 320, 240, BMPData); if (ErrorCode) { //Fehlercode auswerten, Fehlerbehandlung } else { //Bitmap (in diesem Beispiel full screen 320x240=9600Byte) wurde an Position x=0 und y=0, mit einer Breite von 320 Pixel und eine Höhe von 240 Pixel in Grafik-Screen Nummer Null geladen. Da das ganze Bitmap geladen werden sollte, sind BMPoffsetX und BMPoffsetY gleich Null. } //BMPData[9600] mit Bitmapdaten laden (schwarz/weiß), z.B. ein 320x240 Pixel Bitmap mit kleineren //Grafiken für Animationen //… ErrorCode = LUI_Bitmap (DevNum, 1, 50, 30, 10, 15, 25, 25, 320, 240, BMPData); if (ErrorCode) { //Fehlercode auswerten, Fehlerbehandlung } else { // Ein kleines Bitmap wurde an Position x=50 und y=40, mit einer Breite von 25 Pixel und eine Höhe von 25 Pixel in Grafik-Screen Nummer 1 geladen. Das kleine Bitmap hat innerhalb des gesamten Bitmaps die Position x=10 und y=15 (BMPoffsetX=10 und BMPoffsetY=15). Das kleine 25x25 Pixel Bitmap wurde quasi aus dem großen 320x240 Pixel Bitmap (BMPData -Array) an der Position x=10, y=15 “ausgeschnitten” und auf dem LCD an der Position x=50, y=30 eingefügt. } Zitat:
Gruss Cyberaxx |
Re: Bitmap als Pointer auf einem Display ausgeben
Zitat:
Also ein Pointer ist an sich nur ein Zeiger (ok, der Name verrät es doch irgendwie schon). Das klingt trivial, hat aber natürlich ein paar Konsequenzen. Der Pointer der auf 0xA02837B (<- irgendeine Adresse) zeigt, mag zwar gültig sein, aber was steht denn dort an der Adresse? Ein Pointer ist wirklich nur ein Zeiger (man spricht auch von untypisiert), der zwar auf einen Adressbereich zeigt, dir aber durch nichts verrät, was dort steht. GetDIBs erwartet jetzt als letzte zwei Argumente einfach nur Pointer, die auf eine BitmapInfo-Struktur zeigen bzw. auf einen Speicherbereich, der die Bits der Bitmap aufnehmen kann. Wenn du nur eine Lokale Variable p : Pointer anlegst, ist diese nicht initialisiert. Im besten Fall zeigt dieser Zeiger auf 0x0 (= nil), dann bekommst du eine Accessviolation (der Speicherbereich 0 kann nie adressiert werden) und du findest deinen Fehler schnell. Weniger guter Fall wäre es, wenn der einfach mal auf einen ganz anderen Teil deines Programms zeigt. Dann wird die Methode die Bits einfach dort hin schreiben. Dass es nicht unbedingt von Vorteil ist sollte klar sein, aber was genau passiert ist nicht vorhersehbar. Für die Bits gibt es mehrere Möglichkeiten gespeichert zu werden. Du könntest dir z.B. ein TByteDynArray anlegen, dass halt alle Bytes der Bitmap aufnehmen kann oder du benutzt GetMem oder oder oder. Mit GetMem bekommst du auch einfach nur einen Zeiger zurück, damit wird wirklich ein roher Datenbereich (ohne Interpretation) alloziert. Was du mit dem machst ist dann deine Sache. Wichtig ist, der sollte tunlichst auch wieder freigegeben werden. Schau einfach in die Hilfe, da steht dann immer alles Wichtige (wie man Speicher alloziert und freigibt). Ach ja, für den anderen Weg mit dem Array musst du die Adresse der ersten Zelle übergeben (@DeinArray[0]), dass wäre dann der gültige Zeiger. Gruß Der Unwissende [Edit] Edit hat sich erledigt[/Edit] |
Re: Bitmap als Pointer auf einem Display ausgeben
Hey
Ok soweit habe ich das nun verstanden. Oben hatte ich ja beschrieben das "Bitmap: Zeiger auf Array mit Bitmap-Daten" Aber wie setzte ich das dann nun um?
Delphi-Quellcode:
var
Image : Pointer;
Delphi-Quellcode:
Image müsste demnach ein Byte Array sein, sehe ich das richtig?
GetDIB(Handle, Palette, Info^, Image^);
Zitat:
Das Byte Array kann ich das egal welche grösse es hat auf 320x240 Pixel festlegen? oder muss ich das an der aktuellen Grösse des Bildes anpassen? Wie müsste ich das denn umsetzten, oder muss ich die Procedure umschreiben? Es kommt aber noch ein Problem, was ich auch geschrieben habe BMPdataWidth scheint auch nicht zu stimmen aber aus der Doku werd ich da auch nicht ganz schlau. [E] Hab jetzt ne Weile gesucht, bin auch fündig geworden über Arrays aber nun kommt ja das entscheidene wie setz ich denn meine Bilddaten ins Array? [/E] |
Alle Zeitangaben in WEZ +1. Es ist jetzt 04:01 Uhr. |
Powered by vBulletin® Copyright ©2000 - 2025, Jelsoft Enterprises Ltd.
LinkBacks Enabled by vBSEO © 2011, Crawlability, Inc.
Delphi-PRAXiS (c) 2002 - 2023 by Daniel R. Wolf, 2024-2025 by Thomas Breitkreuz