Delphi-PRAXiS

Delphi-PRAXiS (https://www.delphipraxis.net/forum.php)
-   Win32/Win64 API (native code) (https://www.delphipraxis.net/17-win32-win64-api-native-code/)
-   -   Delphi CreateBitmap (https://www.delphipraxis.net/38396-createbitmap.html)

Thunderman 18. Jan 2005 17:53


CreateBitmap
 
Hallo!

Nach langer Zeit bin ich mal wieder an Pascal dran und schon hapert es an der Darstellung einer Grafik. Wenn ich LoadImage() verwende um mein HBITMAP zu erzeugen funktioniert es ja bereits. Doch aus verschiedenen Gründen möchte ich es mit CreateBitmap() erzeugen. Ich habe bereits die Daten des Bitmap hintereinander in den Speicher gelesen, auf den der Pointer s_Image.Data zeigt. Der folgende Code gibt auch ein Handle ungleich 0 zurück. Der Aufruf sollte also erfolgreich gewesen sein:
Delphi-Quellcode:
s_Bitmap := CreateBitmap(s_Image.Width, s_Image.Height, s_Image.Planes, s_Image.Bits, s_Image.Data);
Doch mit dem folgenden Code, der zur Darstellung des mit LoadImage geladenen Bitmaps funktionierte, kann ich es nicht ins Fenster zeichnen:
Delphi-Quellcode:
  s_h_DC := GetDC(s_h_Wnd);
  s_hdc_mem := CreateCompatibleDC(s_h_DC);
  s_temp := SelectObject(s_hdc_mem, s_Bitmap);
  BitBlt(s_h_DC, 0, 0, 480, 320, s_hdc_mem, 0, 0, SRCCOPY);
s_h_Wnd ist das Handle meines Fensters. Ich hoffe hier findet jemand meinen Fehler.

omata 18. Jan 2005 18:40

Re: CreateBitmap
 
Moin,

kann es eventuell daran liegen, dass das Bitmap nicht geräteunabhängig ist.

Delphi-Quellcode:
  Bitmap.HandleType:=bmDIB;
MfG
Thorsten

Thunderman 18. Jan 2005 19:45

Re: CreateBitmap
 
s_Bitmap ist eben nur ein Handle und zeigt auf ein geräteabhängiges Bitmap. Daher verwende ich ja auch CreateCompatibleDC() bzw. SelectObject(). Bitmap.HandleTyp kann ich übrigens nirgends aufrufen, da ich kein TBitmap verwende. Ich habe nur die Pixel im RGB-Format in einem Speicherbereich und möchte diese nun auf einem Fenster ausgeben.

omata 18. Jan 2005 20:37

Re: CreateBitmap
 
Moin,

da man nicht viel von deinem Code sehen kann...

Habe ich mal folgendes probiert...

Delphi-Quellcode:
procedure malen;
var bmp:HBITMAP;
    _HDC, hDC: windows.HDC;
begin
  _HDC := GetDC(Self.Handle);
  hDC := CreateCompatibleDC(_HDC);
  bmp := CreateBitmap(100,100,1,GetDeviceCaps(hDC, BITSPIXEL),nil);
  SelectObject(hDC, bmp);

  BitBlt(hDC, 0, 0, 480, 320, image1.Canvas.Handle, 0, 0, cmSrcCopy); // Nur zum Füllen von bmp

  BitBlt(_HDC, 0, 0, 480, 320, hDC, 0, 0, cmSrcCopy);
end;
das funktioniert.

Als Beispiel habe ich ein Image, dessen Inhalt ich nur über den Handle auf die Form male.

MfG
Thorsten

Thunderman 19. Jan 2005 11:57

Re: CreateBitmap
 
Hallo!

Das ist ja eigentlich genau das, was ich mache. Und wenn ich das Bitmap mit LoadImage() lade funktioniert es auch. Nur wenn ich das Bitmap mit CreateBitmap selbst erzeuge geht es nicht. Ich habe nur leider kein TImage wie bei deinem Beispiel, sondern nur die Bilddaten roh im Speicher. Der Aufruf von CreateBitmap() damit funktioniert auch, aber er zeigt trotzdem kein Bild an. Also muss denke ich noch irgendtwas falsch sein. Hier jetzt das ganze als etwas besserer Beispielcode zum einfachereren nachvollziehen:
Delphi-Quellcode:
procedure Test(Bilddaten: Pointer; Breite, Hoehe, Planes, Bits: Integer);
var
  win_hdc : HDC;
  mem_hdc : HDC;
  bmp    : HBITMAP;
begin
  bmp := CreateBitmap(Breite, Hoehe, Planes, Bits, Bilddaten); // Bitmap aus den Rohdaten erzeugen
  if bmp = 0 then
  begin
    ShowMessage('Fehler');
    Exit;
  end;
  win_hdc := GetDC(win_hWnd); // DC des Fensters
  mem_hdc := CreateCompatibleDC(win_hdc); // einen dazu kompatiblen DC im Speicher erzeugen
  SelectObject(mem_hdc, bmp); // das Bitmap in diesen DC wählen
  BitBlt(win_hdc, 0, 0, Breite, Hoehe, mem_hdc, 0, 0, SRCCOPY);
end;
Wenn man CreateBitmap() hier durch
Delphi-Quellcode:
LoadImage(hInstance,'irgendeinbild.bmp',IMAGE_BITMAP,480,320,LR_LOADFROMFILE)
ersetzt funktioniert das ganze.
Die Bilddaten lade ich mit einem TFileStream, was auch in einer anderen Anwendung wo ich sie mit OpenGL darstelle funktioniert.

omata 19. Jan 2005 18:22

Re: CreateBitmap
 
Moin,

da kann ich dir leider nicht weiterhelfen. Würde ich ja gern, aber ich kann keine Gedanken lesen. ich habe keine Ahnung was du da machst. Dein Hinweis mit dem TFileStream ist ja sehr nett, ich weiss allerdings nicht wie bzw. was du da genau machst.

Sorry
Thorsten

Thunderman 19. Jan 2005 18:31

Re: CreateBitmap
 
Das ist auch nicht sonderlich wichtig, denn wie gesagt enthält Bilddaten nur sämtliche RGB-Werte der Pixel des Bildes hintereinanderweg. Im Grunde ist dafür folgender Code zuständig:
Delphi-Quellcode:
GetMem(Result.Data, InfoHeader.biSizeImage);
S.ReadBuffer(Result.Data^, InfoHeader.biSizeImage);
InfoHeader enthält die wichtigen Informationen aus der *.bmp Datei wie Farbtiefe, Breite und Höhe und eben Bildgröße. Result.Data verwende ich anschließend eben als Bilddaten in der oben genannten Funktion.

omata 19. Jan 2005 20:42

Re: CreateBitmap
 
Gut, ich hatte ein bißchen experimentiert und bekomme etwas gezeichnet. Allerdings sieht das nicht so aus wie mein Bild, weil ich dein kompischen Konzept nicht nachvollziehen kann. Aber vielleicht hilft es dir, weil du die Parameter für CreateBitmap besser kennst...

Delphi-Quellcode:
var Datei:TFileStream;
    Buffer:Pointer;
    bmp:HBITMAP;
    _hDC, hDC:windows.hDC;
    nWidth, nHeight:integer;
begin
  Datei:=TFileStream.Create('Bild.bmp', 0);
  try
    GetMem(Buffer, Datei.Size);
    Datei.ReadBuffer(Buffer^, Datei.size);
    _hDC := GetDC(Self.Handle);
    hDC := CreateCompatibleDC(_hDC);
    bmp := CreateBitmap(100, 100, 1, GetDeviceCaps(hDC, BITSPIXEL), Buffer);
    SelectObject(hDC, bmp);
    BitBlt(_hDC, 0, 0, 100, 100, hDC, 0, 0, cmSrcCopy);
    FreeMem(Buffer, datei.Size);
  finally
    Datei.free;
  end;
end;
MfG
Thorsten

Thunderman 19. Jan 2005 22:44

Re: CreateBitmap
 
Danke schonmal.
Es liegt scheinbar an den Bits bei CreateBitmap() und dem CompatibleDC. Das du nur was komisches siehst liegt auch daran, dass die Ladefunktion des Bitmaps nicht nur aus dem ReadBuffer() besteht, sondern man noch RGB Werte vertauschen muss, etc. Ich versuch nochmal herauszufinden, wie sich die Bits, etc unterscheiden und warum es daher vorher nicht klappte.

Thunderman 19. Jan 2005 23:47

Re: CreateBitmap
 
So,

hier nun die letzten Hinweise, falls mal jemand etwas ähnliches versucht:

-achtet darauf welche Farbtiefe das Device des Fensters hat. In meinem Fall 32bit - das Bitmap war aber nur 24bit.
-Bitmaps in *.bmp Dateien sind (zumindest in meinen Fällen) von hinten nach vorne und von unten nach oben gespeichert.

In meinem konkreten Fall musste ich also die Bilddaten bearbeiten. Zum einen für jeden Pixel einen Alphawert (32bit) hinzufügen und außerdem die Pixeldaten umsortieren. Diese Funktion muss ich demnächst noch optimieren, aber für das erste tut sie es nun und ich kann mich wichtigerem widmen. Danke. Warum ich nicht direkt an die Farbtiefe dachte weiß ich nicht, jedenfalls funktioniert es jetzt. :wall: Gibt es eigentlich eine Möglichkeit Bitmaps mit BitBlt() anzuzeigen, die nicht der Farbtiefe des Devices entsprechen? Ich möchte nämlich nur ungern immer meine Bitmaps entweder auf 32bit hoch oder auf 24bit runterrechnen. Oder kann man davon ausgehen, dass heutzutage jedes Device unter Windows 32bit ist? Ich befürchte eher nicht, 16bit könnte es ja auch noch geben...


Alle Zeitangaben in WEZ +1. Es ist jetzt 04:52 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