Entwickler-Ecke

Multimedia / Grafik - Bitmap aus Arrays erstellen und Image-Objekt zuweisen.


Juniorsatan - Do 25.03.10 14:00
Titel: Bitmap aus Arrays erstellen und Image-Objekt zuweisen.
Hallo

Ich versuche mich gerade daran, aus 3 Arrays (die jeweils für einen Kanal - RGB - stehen) eine Bitmap zu erstellen und diese dann über ein ImageObjekt auf der Form darstellen zu lassen. Das Laden über eine normale Datei klappt tadellos, aber aus dem besagten Array bekomme ich nur ein weißes Bild geliefert. Die Arrays werden zuvor aus einem Stream gelesen.

Prozedur ist die folgende:

Delphi-Quelltext
1:
2:
3:
4:
5:
6:
7:
8:
9:
10:
11:
12:
13:
14:
15:
16:
17:
18:
19:
20:
21:
22:
23:
24:
25:
26:
27:
28:
29:
30:
31:
32:
33:
34:
35:
36:
37:
38:
39:
40:
41:
42:
43:
44:
45:
46:
47:
48:
49:
50:
51:
52:
53:
54:
55:
procedure TForm1.Button5Click(Sender: TObject);
var
len_r, len_g, len_b, i, h, w, n:integer;
dc_r_kanal, dc_g_kanal, dc_b_kanal: TKanal;
begin
IF (OpenDialog1.Execute) THEN
  Begin
    Button2.enabled := TRUE;
    Button3.enabled := TRUE;
    Label1.Caption:= OpenDialog1.Filename + ' geladen.';
    Stream := TFileStream.Create(OpenDialog1.FileName, fmOpenRead);
    try
      Stream.Read(h, SizeOf(h));
      Stream.Read(w, SizeOf(w));
      Stream.Read(len_r, SizeOf(len_r)); // Länge der dyn. Arrays lesen
      Stream.Read(len_g, Sizeof(len_g));
      Stream.Read(len_b, Sizeof(len_g));

      SetLength(rle_r_kanal, len_r);  // Länge der dyn. Arrays setzen
      SetLength(rle_g_kanal, len_g);
      SetLength(rle_b_kanal, len_b);

      FOR i:=0 to high(rle_r_kanal) DO // Arrays befüllen
          Stream.Read(rle_r_kanal[i], SizeOf(rle_r_kanal[i]));
      FOR i:=0 to high(rle_g_kanal) DO // Arrays befüllen
          Stream.Read(rle_g_kanal[i], SizeOf(rle_g_kanal[i]));
      FOR i:=0 to high(rle_b_kanal) DO // Arrays befüllen
          Stream.Read(rle_b_kanal[i], SizeOf(rle_b_kanal[i]));
    finally
      Stream.Free;
    End;
  dc_r_kanal:=rle_decompress(rle_r_kanal);
  dc_g_kanal:=rle_decompress(rle_g_kanal);
  dc_b_kanal:=rle_decompress(rle_b_kanal);
  meinBild:= TBitMap.Create;      // BitMap erstellen
  meinBild.Height:= h;
  meinBild.Width:= w;
  //arrayoutput(dc_r_kanal);
  n:=0;
  FOR h:=0 to meinBild.Height-1 DO
    Begin
      p:= meinBild.ScanLine[h];
      FOR w:=0 to meinBild.Width-1 DO
        Begin
          p^[1]:=dc_r_kanal[n];
          p^[2]:=dc_g_kanal[n];
          p^[3]:=dc_b_kanal[n];     //Wert des Kanals in dyn. Array speichern
          inc(p);             // Zeiger eins weiter verschieben
          inc(n);             // Zählvariable erhöhen
        End;
    End;
  Image1.Picture.Assign(meinBild);
  Image1.Refresh;
  End;
end;


Oder ist die ScanLine Funktion nur zum Lesen und nicht zum manipulieren der Pixel gedacht?

Gruß


Narses - Do 25.03.10 18:18

Moin!

Du setzt die Farbtiefe deines Bildes nicht (meinBild.PixelFormat := pf24bit;) und deine Zeiger-Arithmetik könnte wurstig sein. In deiner Prozedur fehlen auch einige Deklarationen, deshalb kann man das nicht beurteilen (konkret: p).

Beim Überfliegen sag das so aus, also ob du die dynamischen Arrays einzelwertweise liest. Das ist nicht nötig (weil unperformat), die Werte liegen alle hintereinander im Speicher, also kann man das auch am Stück laden/speichern. :idea:

cu
Narses


Juniorsatan - Do 25.03.10 18:48

Der Zeiger p ist wie folgt deklariert:


Delphi-Quelltext
1:
2:
3:
4:
5:
type
  PixArray = array [1..3of Byte;

VAR
  p: ^PixArray;


Danke, die Zuweisung der Farbtiefe war notwendig, jetzt funktioniert es.

Welche Stichworte kannst du mir geben, damit ich mir erlesen kann, wie ich das Array mit einmal (komplett) aus dem Stream lade?


Narses - Do 25.03.10 18:54

Moin!

user profile iconJuniorsatan hat folgendes geschrieben Zum zitierten Posting springen:
Welche Stichworte kannst du mir geben, damit ich mir erlesen kann, wie ich das Array mit einmal (komplett) aus dem Stream lade?
Was anlesen? :gruebel: Einfache Multiplikation wirst du doch wohl noch auswendig beherrschen? :zwinker:

cu
Narses


Juniorsatan - Do 25.03.10 18:59

Dann stelle ich mich nur grad etwas blöd an. Ich denk nochmal kurz drüber nach und falls es dann immernoch nicht will, frag ich nochmal konkre.t ;)