Delphi-PRAXiS

Delphi-PRAXiS (https://www.delphipraxis.net/forum.php)
-   Multimedia (https://www.delphipraxis.net/16-multimedia/)
-   -   Delphi RGB -> Bitmap (https://www.delphipraxis.net/74786-rgb-bitmap.html)

Neutral General 8. Aug 2006 19:05


RGB -> Bitmap
 
Hi,

Also der Threadname siehtn bisschen komisch aus :mrgreen:
Es geht darum das ich einen Stream hab in dem tausenden RGB-Werte stehen.. Ungefähr so:

Zitat:

Zitat von Stream
RGBRGBRGBRGBRGB...RGB

Nun will ich dadrauß en Bitmap machen (TBitmap).
Bisher hab ich das so gemacht das ich alle RGB Werte einzeln ausgelesen habe und die dann mit TBitmap.Canvas.Pixels gemalt habe aber das ist ehhmm "etwas" langsam... :|

Kann das vielleicht nicht etwa so machen :

Delphi-Quellcode:
Stream.Read(Bitmap, SizeOf(Byte)*Pixelanzahl*3);
? :|

So gehts glaub ich nicht aber halt so in der Richtung..

Gruß
Neutral General

arbu man 8. Aug 2006 19:09

Re: RGB -> Bitmap
 
Guck dir doch mal TBitmap.ScanLine in der OH an...

Neutral General 8. Aug 2006 19:10

Re: RGB -> Bitmap
 
Mh kann man die auch zum schreiben von Pixeln benutzen ? o.O^^

JasonDX 8. Aug 2006 21:06

Re: RGB -> Bitmap
 
Hi

Ich hatte mal ein aehnliches Problem, allerdings in C#, ich hab hier das erstellen des Bitmaps an dein Problem angepasst. Eine Uebersetzung sollte nicht die Allergroesste Schwierigkeit sein, da ja eigentlich nur Daten in einen Stream geschrieben werden ;)
Code:
s.Write((ushort)0x4D42);
s.Write((uint)0);
s.Write((uint)0);
s.Write((uint)54);

s.Write((uint)40);
s.Write((uint)width); //Breite
s.Write((uint)height); //Hoehe
s.Write((ushort)1);
s.Write((ushort)24); //24bpp
s.Write((uint)0);
s.Write((uint)0);
s.Write((uint)0xEC4);
s.Write((uint)0xEC4);
s.Write((uint)0);
s.Write((uint)0);

for (int i = 0; i < height; i++)
{
   for (int j = 0; j < width; j++)
   {
      s.Write((byte)0); //B
      s.Write((byte)0); //G
      s.Write((byte)0); //R
   }
   for (int j = 0; j < (4 - (i * 3) % 4); j++) //die 3 bedeutet steht fuer die 24bpp in Byte
      s.Write((byte)0); //Jede Zeile wird auf eine 4Bit-Breite mit 0en aufgefuellt
}

h.Position = 2;
s.Write((uint)h.Length);
Eine genauere Beschreibung hatte ich auf Wikipedia gefunden: *klick*

greetz
Mike

Neutral General 10. Aug 2006 15:03

Re: RGB -> Bitmap
 
Hi,

Danke für den Ansatz ich glaube das wird mir helfen aber eine Zeile kann ich mir leider nicht übersetzen:

Delphi-Quellcode:
for (int j = 0; j < (4 - (i * 3) % 4); j++)
  s.Write((byte)0);
und was ist h ?

Gruß
Neutral General

JasonDX 10. Aug 2006 15:12

Re: RGB -> Bitmap
 
Zitat:

Zitat von Neutral General
Danke für den Ansatz ich glaube das wird mir helfen aber eine Zeile kann ich mir leider nicht übersetzen:

Delphi-Quellcode:
for (int j = 0; j < (4 - (i * 3) % 4); j++)
  s.Write((byte)0);

Das ist eine uebliche Forschleife, mit einer etwas komplizierteren Abbruchbedingung. Das sieht in Delphi ca. so aus, und fuellt die Zeilen auf einen durch 4(byte) teilbare Laenge.
Delphi-Quellcode:
for j := 0 to (4 - (i * 3) mod 4) - 1 do
  //...
Zitat:

Zitat von Neutral General
und was ist h ?

Das war der Stream (ich weiss, einfallsreicher name :oops: )
Im Dateikopf wird auch die Groesse der Datei gespeichert, also die Groesse des Streams, das wird hier eben nachtraeglich erledigt.

greetz
Mike

Neutral General 10. Aug 2006 15:20

Re: RGB -> Bitmap
 
ja aber s ist ja auch ein Stream. Wofür ist denn der h-Stream ?
in den S-Stream wird doch der Bitmap Header und dann das Bitmap selbst geschrieben. Wofür dann der andere Stream?

JasonDX 10. Aug 2006 15:23

Re: RGB -> Bitmap
 
Zitat:

Zitat von Neutral General
ja aber s ist ja auch ein Stream. Wofür ist denn der h-Stream ?
in den S-Stream wird doch der Bitmap Header und dann das Bitmap selbst geschrieben. Wofür dann der andere Stream?

Nicht ganz, ich hatte dafuer einen BinaryWriter genommen (s), der in den Stream (h) geschrieben hat ;)

greetz
Mike

Neutral General 10. Aug 2006 15:28

Re: RGB -> Bitmap
 
Man kann das aber auch nur mit einem Stream machen oder ?

JasonDX 10. Aug 2006 15:53

Re: RGB -> Bitmap
 
Zitat:

Zitat von Neutral General
Man kann das aber auch nur mit einem Stream machen oder ?

Na ja, ein Stream ist fuer diese Loesung gut geeignet. Obs fuer dein Problem noch eine andere, bessere Loesung gibt, weiss ich nicht.

greetz
Mike

Neutral General 10. Aug 2006 16:10

Re: RGB -> Bitmap
 
Les mal was ich geschrieben hab :mrgreen:

JasonDX 10. Aug 2006 16:17

Re: RGB -> Bitmap
 
Zitat:

Zitat von Neutral General
Les mal was ich geschrieben hab :mrgreen:

d'oh, falsch gelesen...

Zitat:

Zitat von Neutral General
Man kann das aber auch nur mit einem Stream machen oder ?

Ja, ich hab auch nur einen Stream (h) verwendet. Da ein Stream (in .NET) nur bytes (bzw. byte-arrays) schreiben kann, gibts da den BinaryWriter (s). Der MSDN-Library durchsuchenBinaryWriter ist kein Stream, sondern eine Klasse, die Daten in einen Stream schreibt. ;)
In der Hoffnung, die Frage jetzt richtig verstanden zu haben :mrgreen:

greetz
Mike

Neutral General 11. Aug 2006 15:38

Re: RGB -> Bitmap
 
Delphi-Quellcode:
 
     SetLength(TGAInfo.Picture, TGAInfo.Header.Width, TGAInfo.Header.Height);
  if TGAInfo.Header.PictureFormat in [1..3] then
  begin
   for j:= 0 to TGAInfo.Header.Height-1 do begin
    for i:= 0 to TGAInfo.Header.Width-1 do begin
     AStream.Read(TGAInfo.Picture[i,j].B, SizeOf(Byte));
     AStream.Read(TGAInfo.Picture[i,j].G, SizeOf(Byte));
     AStream.Read(TGAInfo.Picture[i,j].R, SizeOf(Byte));
    end;
   end;

    BmpStream := WriteBmpHeader(TGAInfo.Header.Width,TGAInfo.Header.Height,TGAInfo.Header.Bpp);
    for j:= 0 to TGAInfo.Header.Height-1 do begin
     for i:= 0 to TGAInfo.Header.Width-1 do begin
      with BmpStream do
      begin
       Write(TGAInfo.Picture[i,j].B,SizeOf(Byte));
       Write(TGAInfo.Picture[i,j].G,SizeOf(Byte));
       Write(TGAInfo.Picture[i,j].R,SizeOf(Byte));
      end;
     end;
     for i:= 0 to (4 - (j * 3) mod 4) - 1 do
       BmpStream.Write(NULL,SizeOf(Byte));
    end;
    BmpStream.Read(FBitmap, BmpStream.Size);
//  FBitmap.LoadFromStream(BmpStream); geht auch nicht
WriteBmpHeader:

Delphi-Quellcode:
function WriteBmpHeader(Width,Height: Longword; bpp: Word): TMemoryStream;
const Null : Longword = 0;
      Dat1 : Word = $4D42;
      Dat2 : Longword = $EC4;
var lwTemp: Longword;
    wTemp : Word;
begin
 Result := TMemoryStream.Create;
 with Result do
 begin
    Write(Dat1,SizeOf(Word));
    Write(NULL,SizeOf(Longword));
    Write(NULL,SizeOf(Longword));
    lwTemp := 54;
    Write(lwTemp,SizeOf(Longword));
    lwTemp := 40;
    Write(lwTemp,SizeOf(Longword));
    Write(Width,SizeOf(Longword));
    Write(Height,SizeOf(Longword));
    wTemp := 1;
    Write(wTemp, SizeOf(Word));
    Write(Bpp,SizeOf(Word));
    Write(NULL, SizeOf(Longword));
    Write(NULL, SizeOf(Longword));
    Write(Dat2,SizeOf(Longword));
    Write(Dat2, SizeOf(Longword));
    Write(NULL, SizeOf(Longword));
    Write(NULL, SizeOf(Longword));
 end;
end;
Es gibt zwar keine AV aber ich bekomme auch nichts zu sehen :(

Gruß
Neutral General

markusj 12. Aug 2006 07:29

Re: RGB -> Bitmap
 
Ähm, vielleicht musst du die Komponente noch refreshen lassen?
Und warum machst du sizeof(byte) ? Nimm doch einfach "1"!

mfG

Markus

EDIT: Hä, das ist leicht verwirrend. Du nimmst dein TGAInfo, schreibst die Bilddaten rein, machst dir dann einen Bitmapheader im Bitmapstream, schreibst die Bilddaten von TGAInfo dort hinein und machst dann BMPStream.read(FBitmap,(BMPStream.size).
Da müsstest du FBitmap.loadfromstream(BMPStream) machen, der erste Befehl ist komplett sinnfrei.

Mein Vorschlag wäre, dass du die Daten aus deinem AStream immer in RGB-Päckchen als drei Bytes (mach dir nen Record!) lädst und dann in Umgekehrter Reihenfolge direkt in dein Bitmap schreibst.
Länge und Breite des Bildes musst du dann im Header festsetzen und bei deiner "Schreibschleife" entsprechend anstelle des TGAInfo verwenden. (Dieser Job schreit nach einem longword, da in den BMP-Specs auch ein Longword verwendet wird).

JasonDX 12. Aug 2006 11:05

Re: RGB -> Bitmap
 
Zitat:

Zitat von Neutral General
Es gibt zwar keine AV aber ich bekomme auch nichts zu sehen :(

Ok, 2 Sachen sind mir beim aufgefallen:
  • Du schreibst NULL statt 0 in den Stream. Und wenn du dir die Definition von NULL ansiehst, es ist verschieden 0 ;)
  • Zitat:

    Zitat von Neutral General
    Delphi-Quellcode:
    //...
         for i:= 0 to (4 - (j * 3) mod 4) - 1 do
           BmpStream.Write(NULL,SizeOf(Byte));
        end;
        BmpStream.Read(FBitmap, BmpStream.Size);

    Ok, Du vergisst, dass am Ende die Groesse des Streams noch ans Offset 2 geschrieben werden muss. Bevor das Bitmap "Fertig" ist, brauchst du noch
    Delphi-Quellcode:
    BmpStream.Position := 2; BmpStream.Write(BmpStream.Size, 4);
Ich weiss nicht genau, das FBitmap ist. Wenn es ein TBitmap ist, dann wird das sicherlich nicht funktionieren.
Das laden des Bitmaps sieht dann so aus:
Delphi-Quellcode:
BmpStream.Position := 0;
FBitmap := TBitmap.Create;
FBitmap.LoadFromStream(BmpStream);
greetz
Mike

SirThornberry 12. Aug 2006 11:28

Re: RGB -> Bitmap
 
@Neutral General: weißt die die Größe des Bitmaps welches in dem Strea mit "RGBRGBRGB..." steht?
Woher kommt der Stream. Wenn du die Größe weißt geht es so:
Delphi-Quellcode:
var lBitmap: TBitmap;
    lPtr  : Pointer;
begin
  lBitmap := TBitmap.Create;
  lBitmap.Width := WidthOfTheStreamBmp;
  lBitmap.Height := HeightOfTheStreamBmp;
  lBitmap.PixelFormat := pf24bit;
  lPtr := lBitmap.ScanLine[lBitmap.Height - 1];
  DeinStream.Read(lPtr^, BytesOfBitmap);
end;

Neutral General 12. Aug 2006 12:41

Re: RGB -> Bitmap
 
:shock:

SirThornberry...
Das ist göttlich genial :shock:
Danke :) :hello:

EDIT: Sagen wir halb-göttlich :mrgreen:
Das Bild steht aufm Kopf xD

Gruß
Neutral General

Phantom1 12. Aug 2006 14:30

Re: RGB -> Bitmap
 
Das iss normal das das Bild auf dem Kopf steht, wenn man ScanLine[Bmp.Height-1] benutzt.

probiere es mal so hier:
Delphi-Quellcode:
var lBitmap: TBitmap;
    lPtr  : Pointer;
    i     : Integer;
begin
  lBitmap := TBitmap.Create;
  lBitmap.Width := WidthOfTheStreamBmp;
  lBitmap.Height := HeightOfTheStreamBmp;
  lBitmap.PixelFormat := pf24bit;
  for i:=0 to lBitmap.Height-1 do begin
    lPtr := lBitmap.ScanLine[i];
    DeinStream.Read(lPtr^, lBitmap.Width*3);
  end;
end;

Neutral General 12. Aug 2006 14:34

Re: RGB -> Bitmap
 
Ja das hatte ich mir auch schon gedacht aber ich hatte irgendwie Angst es auszuprobieren bzw ich hatte befürchtet das das laden dann wieder so ewig lange dauert aber es funktioniert anscheinden doch ;)

thx an alle :)

Gruß
Neutral General


Alle Zeitangaben in WEZ +1. Es ist jetzt 21:58 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 by Thomas Breitkreuz