Laden...

Datenstrom von Graustufen-Pixelwerten (ushorts) in .bmp umwandeln

Erstellt von h0ppel vor 13 Jahren Letzter Beitrag vor 13 Jahren 7.606 Views
Thema geschlossen
H
h0ppel Themenstarter:in
26 Beiträge seit 2009
vor 13 Jahren
Datenstrom von Graustufen-Pixelwerten (ushorts) in .bmp umwandeln

hiho,

ein kollege meinte letztens zu mir, dass es in C# eine Möglichkeit geben würde aus einer gegebenen Auflösung und z.b. eienr Liste von Farbewerten ein BMP zu erstellen, könnte da jetzt aber nix so recht zu finden, weiß da vllt jemand Rat?

mfg

5.742 Beiträge seit 2007
vor 13 Jahren

Hallo h0ppel,

aus einer gegebenen Auflösung und z.b. eienr Liste von Farbewerten ein BMP zu erstellen

Meinst du damit vielleicht die Verwendung von Paletten bzw. indizierten Bitmaps?

Oder den Zugriff auf die Bitmap via Pointer und der LockPixels-Methode?

Ansonsten kannst du auch via Graphics.FromImage beliebig in eine Bitmap zeichen.

Hat der Kollege auch mitgeteilt, wozu man das braucht bzw. was das für Vorteile haben soll? Da könnte evtl. dabei helfen, einzugrenzen, was er genau meinte.

H
h0ppel Themenstarter:in
26 Beiträge seit 2009
vor 13 Jahren

hi,

also ich habe eine Kamera und die liefert einen Datenstrom im ushort format. Das ganze sieht dann so aus, dass ich jetzt erstmal eine .dat Datei habe, welche ebend alle Graustufenwerte für jeden Pixel des Bildes hat. Weiterhin weiß ich noch die Auflösung des Bildes z.B. 120x160. Daraus brauch ich jetzt eine .bmp... im Grunde brauch ich das ganze dann als Datei, damit ich diese dann weiterverarbeiten kann.. also das bloße zeichen würde nicht reichen...

mfg

C
2.121 Beiträge seit 2010
vor 13 Jahren

Das Format von bmp Dateien ist relativ einfach, schau dir das einfach mal an. Dürfte recht oft im Internet beschrieben sein.
Dann erzeugst du dir einen Header mit den passenden Informationen zu den Maßen und so weiter und dahinter packst du dann die Bilddaten.

H
h0ppel Themenstarter:in
26 Beiträge seit 2009
vor 13 Jahren

hi,

danke für die Antworten, habe es jetzt erstmal hinbekommen.
aber wie kann ich jetzt die grauwerte als pixelfarbe festlegen.

Also ich habe ja Werte wie: 23452; 65000 etc. und setze die pixel mit

checks.SetPixel(cols, rows, color);

color = 45677 eght ja net, muss da ganze irgendwie convertieren?!!? aber wie?

mfg

C
2.121 Beiträge seit 2010
vor 13 Jahren

Was haben die Werte für einen Wertebereich? Wenn so eine Fraustufe 2 Bytes hat, nimm das höherwertige Byte davon und setze deine RGB-Felder alle auf diesen Wert.
SetPixel ist übrigens sehr unperformant, du wärst wirklich um einiges schneller wenn du die Datei selber schreiben würdest.
Oder arbeite wenigstens mit ScanLine, siehe Bitmap-Klasse.

H
h0ppel Themenstarter:in
26 Beiträge seit 2009
vor 13 Jahren

hmm okay
Wertebereich ist 2^16

mfg

H
h0ppel Themenstarter:in
26 Beiträge seit 2009
vor 13 Jahren

ich weiß nicht so recht wie das von statten gehen soll, über ein Codebeispiel wäre ich sehr dankbar.

mfg

49.485 Beiträge seit 2005
vor 13 Jahren

Hallo h0ppel,

ich bin mir nicht sicher, ob .NET überhaupt 16bit-Graustufenbilder unterstützt. Im Zweifel musst du eine externe Bibliothek verwenden, die das kann. Oder du schreibst wie von chilic vorgeschlagen die Daten direkt im passenden Format in eine Datei.

herbivore

H
h0ppel Themenstarter:in
26 Beiträge seit 2009
vor 13 Jahren

Unterstützt wird das ganze schon denk ich mal da:

PixelFormat.Format16bppGrayScale

aber mein Problem ist, dass ich ushort werte habe. Aber C# kann ja nix anfangen mit einfachen Zahlen wie 45654.
Diese muss ich doch erst in einen gängigen Farbwert konvergieren, sodass ich hinterher das ganze in der Form:

Color.FromArgb();

habe?

mfg

5.742 Beiträge seit 2007
vor 13 Jahren

Aber C# kann ja nix anfangen mit einfachen Zahlen wie 45654.
Diese muss ich doch erst in einen gängigen Farbwert konvergieren, sodass ich hinterher das ganze in der Form

Nein, du kannst die Werte direkt in die Bitmap (bzw. deren Daten-Array) schreiben - siehe dazu die Doku von Bitmap.LockBits.

H
h0ppel Themenstarter:in
26 Beiträge seit 2009
vor 13 Jahren

sorry falls ich auf dem Schlauch stehe,
aber hier wird doch ganz klar ein byte verlangt und ich habe doch mein ushort?

System.Runtime.InteropServices.Marshal.Copy(ptr, rgbValues, 0, bytes);

5.742 Beiträge seit 2007
vor 13 Jahren

aber hier wird doch ganz klar ein byte verlangt und ich habe doch mein ushort

Du musst halt immer ein Short in zwei Byte zerlegen und nacheinander schreiben - die Endianess musst du aber wohl durch Trial&Error herausfinden 😉

Bei einer ARGB-Bitmap stellen z.B. immer 4 Byte ein Pixel dar: Ein Byte A, ein Byte R, ein Byte G und ein Byte B.

C
2.121 Beiträge seit 2010
vor 13 Jahren

Du musst halt immer ein Short in zwei Byte zerlegen und nacheinander schreiben

Nö nur immer eines der beiden Bytes.

5.742 Beiträge seit 2007
vor 13 Jahren

Nö nur immer eines der beiden Bytes.

Wieso das?

C
2.121 Beiträge seit 2010
vor 13 Jahren

Weil der Wertebereich eines Graustufenwerts von der Kamera 2 Bytes groß ist, der Wertebereich von RGB ist aber nur 1 Byte.
Also muss er den ushort zwar schon in 2 Bytes zerlegen, davon aber nur das höherwertige speichern.

S
248 Beiträge seit 2008
vor 13 Jahren

Hallo h0ppel,

als erstes solltest du wissen, welchen Wertebereich das zu konvertierende Bild hat. Dann musst du dir überlegen, wie du die Werte von 16 bit, nach vermutlich 8bit, konvertieren willst. Hierzu würde ich eine Histogramm- oder eine Min/Max-Skalierung verwenden.

Diese spuckt dir dann zwei Werte aus:
zb. min=32000 max=35000.

Damit kannst du dann jeden Pixel auf 8bit skalieren:
c = 255/(max-min)
y = (x - min) * c

Damm brauchst du ein Bitmap mit passender Palette (256 Farben vermutlich graustufen).
Einfach gleiche Größe erzeugen und jeden Pixel konvertieren.

spooky

5.742 Beiträge seit 2007
vor 13 Jahren

Weil der Wertebereich eines Graustufenwerts von der Kamera 2 Bytes groß ist, der Wertebereich von RGB ist aber nur 1 Byte.

RGB sind doch 3 Byte (1 Byte pro Kanal), oder?
Ein 16bit-Greyscale Image sollte dann ja eigentlich 2 Byte pro Pixel haben - also genau ein short bzw. ushort.

C
2.121 Beiträge seit 2010
vor 13 Jahren

Ein 16bit-Greyscale Image sollte dann ja eigentlich 2 Byte pro Pixel haben

Das von der Kamera hat ja wirklich 2 Byte pro Pixel. Aber wenn ein RGB Bild gewünscht ist, braucht man wie du ja schon selber sagtest 3 Bytes. Nachdem es ein Graustufenbild ist, haben die Bytes für RGB jeweils den selben Wert. Und dieser Wert ist ein Byte, das aus dem 2-Byte Wert der Kamera gemacht werden muss.

49.485 Beiträge seit 2005
vor 13 Jahren

Hallo chilic,

wo hat der OP hat was von RGB-Bild oder 8bit-Graustufenbild gesagt? Es geht darum, aus 16bit-Werten auch tatsächlich ein 16bit-Graustufenbild zu erzeugen. Siehe oben.

herbivore

C
2.121 Beiträge seit 2010
vor 13 Jahren

winSharp93 hat das in seinem letzten Beitrag vermutet, aber ob der Fragesteller es auch wirklich so will? Es ging ja schon eher immer um ushort->Byte und RGB.
Vielleicht sagt hoppel ja nochmal genau was am Ende rauskommen soll. Solls denn wirklich 16 Bit Graustufe sein oder reicht eine gängige Auflösung von 8 Bit und du weißt nur nicht wie du diese 8 Bit bekommst?

H
h0ppel Themenstarter:in
26 Beiträge seit 2009
vor 13 Jahren

hi,

brauchte erstmal einen Tag Erholung, nachdem ich mich Stunden und Tage lang mit dem Problem rumgeschlagen haben.

So zuerst nochmal das Gegeben und Gesucht:

Ich bekomme von einer Kamera Daten im ushort Format welche dann so aussehen:

22672
22032
22256
22240
22416
22720
22640
22832
23360
22848
24128
23984
24176
23856
24432
23920
24496
25296
25280
24704
24256
24640
24656
24256

momentan habe ich diese in einer. dat vorliegen, später möchte ich dann direkt den Stream verarbeiten. Weiterhin weiß ich die Auflösung ( z.B: 320 x 240 ), sowie den Wertebereich, welcher maximal bis 2^16 geht. Das Maximum ist also 65536. Dieser Wert soll als überstrahlt gewertet werden.

So... aus diesen Daten muss ich jetzt eine Bitmap erstellen, welche dann weiterverarbeitet, wird mithilfe einer Fremdbibiothek.

Das Problem, welches daraus folgt, ist es eine funktionierende Bitmap zu erstellen.
Bis jetzt habe ich 4 Möglichkeiten identifiziert dies zu bewerkstelliegen 😃

  1. über:
bmp.SetPixel(rows, cols, color);

wobei ich einen Farbwert in der Form:

color = Color.FromArgb(a, b, c);

brauche. Weiterhin ist die Methode über Setpixel verdammt langsam.

  1. über Lockbits
BitmapData bmpData = bmp.LockBits(new Rectangle(0, 0, bmp.Width, bmp.Height),ImageLockMode.WriteOnly, bmp.PixelFormat);

               Marshal.Copy(ptr,CamData,0,test);

So hier brauche ich den Farbwert in Byte Form. Was ich ja nicht habe... Dafür ist die Methode schön schnell.

  1. Die Wohl schnellste Methode schein über eine ColorMatrix möglich zu sein, habe mich damit aber auch noch nicht so recht beschäftigt, bzw weiß nichts über die Geeigentheit, gehe aber mal davon aus, dass auch diese nichts mit ushort Werten anfangen kann...

  2. ich mache alles manuell über

fileStream.write

Fazit: Wie ich es dreh und wende, ich denke ich muss meine ushort Werte irgendwie umwandeln. Momentan mache ich es ganz primitiv über:

int temp = CamData[i] / 257;
                    color = Color.FromArgb(temp, temp, temp);
                    bmp.SetPixel(rows, cols, color);

bringt zwar im Grunde auch nix, aber so habe ich wenigstens Grauwerte.
Das Ergebniss sieht man im Dateianhang

Weiterhin kommt es zu folgender Fehlermeldung: Only BMP depths of (8,24) are supported. Not 32
wenn ich das falsche Pixelformat wähle. Der Fehler entsteht, wenn ich das erstellte Bild mit der erwähnten Fremdbibliothek laden will. Irgendwo habe ich auch gelesen, dass z.B: PixelFormat.Format16bppGrayScale nicht richtig funtionieren würden.

Mehr fällt mir im Moment nicht dazu ein, bekomm es ebend einfach nicht hin, diese Graustufen Werte richtig umzuformen bzw in der richtigen Form zu übergeben.

Danke für die Hilfe, wäre super, wenn ihr mir noch ein paar tipps geben könntet!

mfg

49.485 Beiträge seit 2005
vor 13 Jahren

Hallo h0ppel,

wie schon mehrfach vorgeschlagen kannst du einfach direkt (z.B. per BinaryWritrer) eine Bitmap-Datei schreiben (Header + Pixeldaten). Das Format ist sehr einfach und im Netz gut dokumentiert.

Der Thread dreht sich im Kreis.

herbivore

Thema geschlossen