Delphi-PRAXiS

Delphi-PRAXiS (https://www.delphipraxis.net/forum.php)
-   Object-Pascal / Delphi-Language (https://www.delphipraxis.net/32-object-pascal-delphi-language/)
-   -   Delphi Bitmap aus einem Array von Farbwerten erzeugen (https://www.delphipraxis.net/106211-bitmap-aus-einem-array-von-farbwerten-erzeugen.html)

daschaos 7. Jan 2008 13:07


Bitmap aus einem Array von Farbwerten erzeugen
 
Gibt es eine Möglichkeit, ein Bitmap aus einem Array zu erzeugen, in welchem ich Farbwerte pro Pixel abgelegt hab?
Das Problem ist, dass ich für mein Bitmap aufgrund verschiedener Lichtverhältnisse etc. jeden Pixel einzeln berechnen
muss und diese dann mit SetPixel() zeichne. Das ist natürlich elend langsam. Deswegen überlege ich mir ob ich nicht zuerst
alle Pixel berechnen könnte und diese jeweils im Array abspeichere und anschließend aus diesen Werten ein Bitmap erzeuge?
Gibts da ne Möglichkeit?

Danke schonmal!

Thanatos81 7. Jan 2008 13:14

Re: Bitmap aus einem Array von Farbwerten erzeugen
 
Wirf mal einen Blick in die OH auf ScanLine, oder auch hier im Forum. Damit kannst du auf die einzelnen Zeilen eines Bitmaps als Array zugreifen, das ist wesentlich fixer als über .Pixels[x,y] zu arbeiten.

SirThornberry 7. Jan 2008 13:42

Re: Bitmap aus einem Array von Farbwerten erzeugen
 
genauer gesagt gibt dir Scanline die Adresse einer Zeile des Bildspeichers zurück. Du musst also nicht für jede Zeile Scanline abfragen sondern kannst auch einmal mit Scanline dir die Adresse des Puffers holen und dann das Array komplett rüber kopieren.

daschaos 7. Jan 2008 14:01

Re: Bitmap aus einem Array von Farbwerten erzeugen
 
Hm, ehrlich gesagt weiß ich noch nich so recht, wie ich das jetzt machen muss...

Ich hab also mein PixelArray[x, y] und mein Bmp, welches ich mit den Daten aus dem PixelArray füllen will.
Dann hätte ich sowas:

Delphi-Quellcode:
function Blubb;
var
  Row: Pointer;
  Bmp: TBitmap;
begin
  ...

  for iy := Low(PixelArray[0]) to High(PixelArray[0]) do
  begin
    Row := Bmp.Scanline[iy];
   
    for ix := Low(PixelArray) to High(PixelArray) do
    begin
      ??? 
      ??? := PixelArray[ix, iy];
      ???
    end;
  end;

  ...
end;
Wie genau bekomm ich die Werte nun in mein Bmp? :coder2:

Muetze1 7. Jan 2008 14:43

Re: Bitmap aus einem Array von Farbwerten erzeugen
 
Zitat:

Zitat von daschaos
Gibt es eine Möglichkeit, ein Bitmap aus einem Array zu erzeugen, in welchem ich Farbwerte pro Pixel abgelegt hab?

In welchem Format liegen diese Farbwerte in dem Array vor? Sind das Palettenindizies oder sind es schon rot/grün/blau Anteile?

/EDIT: Da du sie vorher direkt mit Pixels zugewiesen hast, liegen sie wohl in TColor vor. Dann wie folgt:

Delphi-Quellcode:
function Blubb;
var
  lPixel: PRGBQuad;
  Bmp: TBitmap;
begin
    // du musst dafür sorgen, dass die Ablage der Pixeldaten auch im gewünschten Format vorliegt. Dazu
    // schau dir die Eigenschaft PixelFormat von TBitmap an.
    // Mein Beispiel geht von pf32bit aus, also 4 Byte pro Pixel: Rot, Grün, Blau, reserved
 
  Bmp.PixelFormat := pf32bit;

  for iy := Low(PixelArray[0]) to High(PixelArray[0]) do
  begin
    lPixel := Bmp.Scanline[iy]; // gibt den Zeiger auf den linken Pixel der Zeile iy zurück
      // alle folgenden Pixel liegen dann direkt hinter dem ersten
   
    for ix := Low(PixelArray) to High(PixelArray) do
    begin
      lPixel^.rgbRed := GetRValue(PixelArray[ix, iy]);
      lPixel^.rgbGreen := GetGValue(PixelArray[ix, iy]);
      lPixel^.rgbBlue := GetBValue(PixelArray[ix, iy]);
      lPixel^.rgbReserved := 0;

        // diese Funktion verschiebt das Ziel des Zeigers um die Grösse der Datenstruktur auf die er zeigt.
        // Das ist in diesem Falle direkt ein TRGBQuad bestehend auf Rot, Grün, Blau und reserved (jeweils ein Byte)
        // also insgesamt 4 Bytes, also 32 Bit. Diese Struktur entspricht genau den Pixelformat eines Pixels. Somit
        // verschiebt Inc(lPixel) den Zeiger genau so, dass er danach auf die Stelle 4 Bytes später zeigt.
      Inc(lPixel);
    end;
  end;
end;

daschaos 7. Jan 2008 14:52

Re: Bitmap aus einem Array von Farbwerten erzeugen
 
Der Pixel wird momentan folgendermaßen berechnet und abgespeichert:

Pixel := (IntensityA + Max(0, IntensityS * CosA)) / 255;

Red := Round(Byte(LayerColor)* Pixel);
Green := Round(Byte(LayerColor shr 8) * Pixel);
Blue := Round(Byte(LayerColor shr 16) * Pixel);

PixelArray[ix, iy] := RGB(Red, Green, Blue);

SirThornberry 7. Jan 2008 14:59

Re: Bitmap aus einem Array von Farbwerten erzeugen
 
wenn dein Array die gleiche Größe hat wie das Bild später (also gleiche Bytezahl) kannst du auch komplett den gesamten Speicher davon kopieren.

Muetze1 7. Jan 2008 15:00

Re: Bitmap aus einem Array von Farbwerten erzeugen
 
Zitat:

Zitat von daschaos
Der Pixel wird momentan folgendermaßen berechnet und abgespeichert:

Na ist doch super - das kannst du ja denn direkt anstatt in dem Pixel Array dem Bild zuweisen - wie beim Codebeispiel von mir sieht man die einzelnen RGB Anteile gut.

Aber der Vollständigkeit halber nochmal der Code mit GetRValue()/GetGValue() und GetBValue():

Delphi-Quellcode:
Pixel := (IntensityA + Max(0, IntensityS * CosA)) / 255;

Red := Round(GetRValue(LayerColor)* Pixel);
Green := Round(GetGValue(LayerColor) * Pixel);
Blue := Round(GetBValue(LayerColor) * Pixel);
Mit den Funktionen wird es deutlich lesbarer als das rumgeshifte um die Anteile zu ermitteln.

Um das ganze nochmals zu beschleunigen könntest du LayerColor vor den beiden Schleifen zum füllen des Arrays einmalig umwandeln und z.B. in einer Variablen des Typs TRGBQuad ablegen. Damit entfällt das rumrechnen mit jedem Durchlauf.

Zitat:

Zitat von SirThornberry
wenn dein Array die gleiche Größe hat wie das Bild später (also gleiche Bytezahl) kannst du auch komplett den gesamten Speicher davon kopieren.

Das klappt nur, wenn das Array:

1. nicht den ElementTyp TColor hat (B und R vertauscht)
2. Das Padding von TBitmap bzw. DIB beachtet wird. Also es muss pf32bit / TRGBQuad kompatibel sein

daschaos 7. Jan 2008 16:01

Re: Bitmap aus einem Array von Farbwerten erzeugen
 
Ihr seid toll, danke! Also ich hab noch nich alles von dem verstanden, was ihr schreibt :), aber das kommt noch. Tausend Dank für die schnelle Hilfe! Ich versuch dann mal alles ein bißchen umzumodeln...


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