AGB  ·  Datenschutz  ·  Impressum  







Anmelden
Nützliche Links
Registrieren
Zurück Delphi-PRAXiS Programmierung allgemein Multimedia Delphi Bitmap als Pointer auf einem Display ausgeben
Thema durchsuchen
Ansicht
Themen-Optionen

Bitmap als Pointer auf einem Display ausgeben

Ein Thema von Cyberaxx · begonnen am 31. Mär 2006 · letzter Beitrag vom 2. Apr 2006
Antwort Antwort
Seite 1 von 2  1 2      
Benutzerbild von Cyberaxx
Cyberaxx

Registriert seit: 15. Jul 2005
311 Beiträge
 
Delphi XE5 Professional
 
#1

Bitmap als Pointer auf einem Display ausgeben

  Alt 31. Mär 2006, 00:31
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:
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'
Habe dann überall gesucht und bin dann auf etwas gestossen, was mit das Bitmap in einen Pointer setzt.

Delphi-Quellcode:
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;
Die Funktion leistet auch wunderbare Dienste. Einzieger Nachteil ist es ist Vertikal gespiegelt. Das ist natürlich nicht gewollt!

Habe es dann vor der Ausgabe auf das Display vertikal gespeigelt.

Delphi-Quellcode:
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;
Damit habe ich nun auf dem Display mein Bild so wie es sein soll.

Delphi-Quellcode:
Spiegeln(VisBuff);
BMPtoPointer(VisBuff);
Diese Funktion wird z.Z. alle 50ms aufgerufen, da sie das Audiospectrum wieder gibt.

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
Daniel
  Mit Zitat antworten Zitat
Benutzerbild von himitsu
himitsu

Registriert seit: 11. Okt 2003
Ort: Elbflorenz
44.184 Beiträge
 
Delphi 12 Athens
 
#2

Re: Bitmap als Pointer auf einem Display ausgeben

  Alt 31. Mär 2006, 11:06
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:
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;
PS: falls du Lust hast ... es geht auch kürzer (mußt nicht jedesmal INTEGER einzeln angeben) ^_^
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';
$2B or not $2B
  Mit Zitat antworten Zitat
Benutzerbild von Cyberaxx
Cyberaxx

Registriert seit: 15. Jul 2005
311 Beiträge
 
Delphi XE5 Professional
 
#3

Re: Bitmap als Pointer auf einem Display ausgeben

  Alt 31. Mär 2006, 11:21
Guten Morgen,

das will leider nicht so...

Delphi-Quellcode:
  var
    Image : Pointer;
    ImageSize : DWord;
  begin
    with Bitmap do
    begin
      GetDIBSizes(Handle, InfoSize, ImageSize);
Da fehlt das InoSize, habs hinzugefügt aber er braucht doch die Info

Delphi-Quellcode:
GetDIB(Handle, Palette, nil, Image^);

[Fehler] LUI.pas(173): Konstantenobjekt kann nicht als Var-Parameter weitergegeben werden
Daniel
  Mit Zitat antworten Zitat
Benutzerbild von himitsu
himitsu

Registriert seit: 11. Okt 2003
Ort: Elbflorenz
44.184 Beiträge
 
Delphi 12 Athens
 
#4

Re: Bitmap als Pointer auf einem Display ausgeben

  Alt 31. Mär 2006, 11:24
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.
$2B or not $2B
  Mit Zitat antworten Zitat
Benutzerbild von Cyberaxx
Cyberaxx

Registriert seit: 15. Jul 2005
311 Beiträge
 
Delphi XE5 Professional
 
#5

Re: Bitmap als Pointer auf einem Display ausgeben

  Alt 31. Mär 2006, 11:28
Wenn Du mir kurz helfen würdest damit ich weiss wie ich drauf zugreifen sollte.

Ist ja das erste mal das ich damit arbeite...
Daniel
  Mit Zitat antworten Zitat
Benutzerbild von himitsu
himitsu

Registriert seit: 11. Okt 2003
Ort: Elbflorenz
44.184 Beiträge
 
Delphi 12 Athens
 
#6

Re: Bitmap als Pointer auf einem Display ausgeben

  Alt 31. Mär 2006, 13:18
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)
$2B or not $2B
  Mit Zitat antworten Zitat
Der_Unwissende

Registriert seit: 13. Dez 2003
Ort: Berlin
1.756 Beiträge
 
#7

Re: Bitmap als Pointer auf einem Display ausgeben

  Alt 31. Mär 2006, 19:08
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
  Mit Zitat antworten Zitat
Benutzerbild von Cyberaxx
Cyberaxx

Registriert seit: 15. Jul 2005
311 Beiträge
 
Delphi XE5 Professional
 
#8

Re: Bitmap als Pointer auf einem Display ausgeben

  Alt 31. Mär 2006, 19:17
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:
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.
}
Könnte mir jemand helfen, was es mit dem Wert auf sich hat?


Zitat von Der_Unwissende:
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).
Könntest Du mir das bitte etwas genauer erklähren. Habe keine Ahnung von Pointern, da ich sie bisher nie nutzte.

Gruss

Cyberaxx
Daniel
  Mit Zitat antworten Zitat
Der_Unwissende

Registriert seit: 13. Dez 2003
Ort: Berlin
1.756 Beiträge
 
#9

Re: Bitmap als Pointer auf einem Display ausgeben

  Alt 1. Apr 2006, 11:27
Zitat von Cyberaxx:
Zitat von Der_Unwissende:
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).
Könntest Du mir das bitte etwas genauer erklähren. Habe keine Ahnung von Pointern, da ich sie bisher nie nutzte.
Aber gerne doch.
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]
  Mit Zitat antworten Zitat
Benutzerbild von Cyberaxx
Cyberaxx

Registriert seit: 15. Jul 2005
311 Beiträge
 
Delphi XE5 Professional
 
#10

Re: Bitmap als Pointer auf einem Display ausgeben

  Alt 1. Apr 2006, 18:21
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;
GetDIB(Handle, Palette, Info^, Image^); Image müsste demnach ein Byte Array sein, sehe ich das richtig?

Zitat:
Der muss auf ein Feld zeigen, dass groß genug ist um alle Pixelinfos der Bitmap aufzunehmen (also Width * Height * PixelFormat in Byte).
PixelFormat könnte ich demnach weg fallen lassen, da ich nur 1Bit farbtiefe auf dem Display ausgeben kann. Sah man bei meinem Beispiel nicht aber in konvertiere das Bitmap vorher zu 1Bit runter.

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]
Daniel
  Mit Zitat antworten Zitat
Antwort Antwort
Seite 1 von 2  1 2      


Forumregeln

Es ist dir nicht erlaubt, neue Themen zu verfassen.
Es ist dir nicht erlaubt, auf Beiträge zu antworten.
Es ist dir nicht erlaubt, Anhänge hochzuladen.
Es ist dir nicht erlaubt, deine Beiträge zu bearbeiten.

BB-Code ist an.
Smileys sind an.
[IMG] Code ist an.
HTML-Code ist aus.
Trackbacks are an
Pingbacks are an
Refbacks are aus

Gehe zu:

Impressum · AGB · Datenschutz · Nach oben
Alle Zeitangaben in WEZ +1. Es ist jetzt 14:45 Uhr.
Powered by vBulletin® Copyright ©2000 - 2024, Jelsoft Enterprises Ltd.
LinkBacks Enabled by vBSEO © 2011, Crawlability, Inc.
Delphi-PRAXiS (c) 2002 - 2023 by Daniel R. Wolf, 2024 by Thomas Breitkreuz