Graphische Ausgabe eines Byte-Arrays!
-
Hallöle!
Ich krampfe gerade bei meiner ersten Kameransteuerung herum, deshalb hoffe ich, dass Ihr mir kurz helfen könnt. Die Konsolen-Ansteuerung funktioniert schon(einfache Aufnahme und Abspeicheln), nun versuche ich eine direkte graphische Ausgabe zu schreiben. Dazu möchte ich Windows Forms mit der C++/CLI-Syntax verwenden. In einem ersten Schritt habe ich einfach ein Array mit einem linearen Graustufenverlauf angelegt(die Kamera kann auch nur s/w). Das Array soll dann graphisch ausgegeben werden. Der Code, den ich mir zusammengebastelt habe, funktioniert auch, allerdings erscheint er mir etwas umständlich. Ich bin noch die alte MFC Variante gewohnt, wo man mit den Device-Contents gearbeitet hat, was ja hier bei den Forms nicht mehr der Fall zu sein scheint. Vllt schaut man sich den code kurz an und sagt was dazu. Als Frage formuliert: wie bekomme ich ein array aus byte-werten am besten graphisch ausgegeben?
Danke!!
G
Graphics ^ g = e->Graphics; Bitmap^ myBitmap = gcnew Bitmap(256,256); for(int x=0;x<256;x++){ for(int y=0;y<256;y++){ myBitmap->SetPixel(x,y,System::Drawing::Color::FromArgb(x,x,x)); }} g->DrawImage(myBitmap, 1, 1);
-
LoKi.aK schrieb:
Als Frage formuliert: wie bekomme ich ein array aus byte-werten am besten graphisch ausgegeben?
nicht mit SetPixel ... das ist schrecklich langsam ... wenn Du schon HBITMAP hast, dann könnte Image::FromHBitmap das richtige sein ... ansonsten gibt es noch diverse andere Methoden die Bitmap direkt ins Image zu kopieren ... da muss ich allerdings aufgeben
Graphics ^ g = e->Graphics; // ...
in welchem Event arbeitst Du das ab?
-
@mogel: Danke!
Ich habe mir die Beschreibung zu Image::FromHBitmap in der msdn-referenz durchgelesen, allerdings ist mir nicht klar, wie damit mein BYTE-array graphisch darstellen soll. Es wäre nett, wenn Du mir in ein paar Zeilen Code darstellen würdest, wie Du Dir das vorstellst.
Die paar Zeilen Code stehen in der Paint-Methode des Formulars, in dem das array ausgegeben werden soll.
Mit der MFC war es damals doch ganz einfach, ein array an ein bitmap zu übergeben. Etwas vergleichbares muss es auch bei den forms geben!!!!
-
LoKi.aK schrieb:
Ich habe mir die Beschreibung zu Image::FromHBitmap in der msdn-referenz durchgelesen, allerdings ist mir nicht klar, wie damit mein BYTE-array graphisch darstellen soll. Es wäre nett, wenn Du mir in ein paar Zeilen Code darstellen würdest, wie Du Dir das vorstellst.
kann ich leider nicht machen ... da ich es selber noch nicht gemacht habe
Mit der MFC war es damals doch ganz einfach, ein array an ein bitmap zu übergeben. Etwas vergleichbares muss es auch bei den forms geben!!!!
das sollte so ähnlich sein ... MFC ist AFAIK nichts weiter als der Versuch die Windows-API auf OOP umzusetzen ... wenn Du Quellcode dazu hast, kann man da ja mal schauen
-
LoKi.aK schrieb:
@mogel: Danke!
Etwas vergleichbares muss es auch bei den forms geben!!!!In C++/CLI und in C# (unter Verwendung von unsafe) kann man direkt in den internen Speicherbereich der Bitmap-Klasse schreiben.
Schau dir die Member LockBits(), UnlockBits() und Scan0 der Bitmap-Klasse an.
Auf Codeproject gibt es jede Menge Beispiele zur Bildbearbeitung in C#.
-
Danke nn!
Also, ich habe mich u.a. auf der codeproject-seite umgeschaut und zwei Möglichkeiten aufgetan. Scheinbar gibt es die Stream-Methode und die Methode über Lock/Unlock/Marshal.Copy. Für beide habe ich die gefundenen Code-Schipsel eingefügt:
1.Stream-Methode:http://social.msdn.microsoft.com/forums/en-US/winforms/thread/e57f7731-c703-4c17-b1a2-32b155f9b745/public static Bitmap BytesToBitmap(byte[] byteArray) { using (MemoryStream ms = new MemoryStream(byteArray)) { Bitmap img = (Bitmap)Image.FromStream(ms); return img; }}
2.Lock/Unlock/Marshal.Copy: http://social.msdn.microsoft.com/forums/en-US/winforms/thread/54afcc4a-31f1-41d6-a2a6-61be1421668f/
public static Bitmap FromByteArray(byte[] ByteArray, Size Size) { Bitmap bmp = new Bitmap(Size.Width, Size.Height, PixelFormat.Format24bppRgb); BitmapData bmpdata = bmp.LockBits(new Rectangle(0, 0, Size.Width, Size.Height),ImageLockMode.WriteOnly, PixelFormat.Format24bppRgb); IntPtr ptr = bmpdata.Scan0; System.Runtime.InteropServices.Marshal.Copy(ByteArray, 0, ptr, ByteArray.Length); bmp.UnlockBits(bmpdata); return bmp;}}
Sind beide Ansätze gleichwertig, oder gibt es Unterschiede? Wenn ja, in welcher Hinsicht? In Bezug auf meine geplante Kamera-Ansteuerung(live-Bild) wäre doch eigentlich die stream-variante das Mittel der Wahl, oder?
P.S.: Auf der codeproject-seite ist mir noch eine weiter Möglichkeit aufgefallen: http://www.codeproject.com/Messages/3073485/Re-UnlockBits-releases-my-Byte-Array.aspx
// Make a 120x120 24bpp bitmap - initialize pixels to all red pBitmapBits = new unsigned char[120 * 120 * 3]; for (int x = 0; x < (120*120*3); x += 3) { pBitmapBits[x+0] = 0; pBitmapBits[x+1] = 0; pBitmapBits[x+2] = 255; } testBitmap = gcnew Bitmap(120, 120, 120*3, PixelFormat::Format24bppRgb, [b]IntPtr(pBitmapBits[/b]));
Ich werde alle Möglichkeiten ausprobieren, mal sehen, was dabei herumkommt! Für Hinweise und Anregungen bin ich immer dankbar!
-
Hallo!
Scheinbar scheitere ich schon an ein paar Zeilen Code. Ich habe alles ausprobiert, finde aber nicht den Fehler. Es erscheint permanent die Fehlermeldung:
Eine nicht behandelte Ausnahme des Typs "System.ArgumentException" ist in System.Drawing.dll aufgetreten. Ungültiger Parameter<<
Hat jemand von Euch eine Ahnung, wo der Fehler liegen könnte?private: System::Void Onpaint(System::Object^ sender, System::Windows::Forms::PaintEventArgs^ e) { Graphics ^g = e->Graphics; array<Byte>^testar=gcnew array<Byte>(256*256); for(int x=0;x<256;x++){ for(int y=0;y<256;y++){ testar[x+256*y]=x; }} MemoryStream ^memstr = gcnew MemoryStream(testar); Bitmap ^myBitmap = gcnew Bitmap(memstr); }
Danke!
-
Hallo,
du darfst nicht einfach nur die reinen Pixel-Daten in ein Array packen, damit kann der "einfache" Konstruktor, der hier:
Bitmap ^myBitmap = gcnew Bitmap(memstr);
verwendet wird, nichts anfangen. Bei den anderen Beispielen (bis auf die FromStream-Methode, auch da müssen die Daten passen, sonst gibt's das gleiche Problem), die du schon gefunden hast, ist immer klar, welches Pixelformat, Höhe und Breite die Bitmap hat, aber hier fehlt die Information.
MfG,
Probe-Nutzer
-
Danke an Unbekannt!
Der Gedanke ist mir auch schon gekommen, allerdings ergeben sich bei Deinem Ansatz zwei Fragen. Zunächst wüsste ich nicht, wie ich den Stream mit dem Bitmap verknüpfen soll, wenn ich es nicht über den Konstruktor mache. Eine entsprechende Methode ist mir nicht bekannt. Zum anderen frage ich mich, wie der Bitmap-Konstruktor(Stream) funktioniert. Im Stream müssen dann doch alle notwendigen Inforamtionen, wie Dimensionen/Pixelformat etc. hinterlegt sein, damit die Instanz passen initialisiert werden kann. Das bedeutet doch für mich, dass ich meinem Stream die Infos irgendwie mitgeben muss, right?
Desweiteren ist mir noch eine Möglichkeit aufgefallen. Es gibt noch einen weiteren Konstruktor der BitmapKlasse: Bitmap-Konstruktor(Int32,Int32,Int32,PixelFormat,IntPtr) ->http://msdn.microsoft.com/de-de/library/zy1a2d14.aspx
Dieser beinhaltet eigentlich alle notwendigen Angaben. Auf der Hilfe-Seite heißt es beim letzten Paramter:System.IntPtr: Zeiger auf ein Array von Bytes, das die Pixeldaten enthält.
Klingt ja zunächst vielversprechend, leider meckert der Compiler, wenn ich versuche ihm das Byte-Array zu übergeben. Der Grund ist mir schleierhaft, da es wiederum in der msdn-Hilfe heisst, dass es sich bei IntPrt um einen plattformabhängigen Typ zur Darstellung von Zeigern und Handles handelt. Warum bockt er dann bei einem Byte-Array?
Zum Schluss noch eine eher generelle Frage: Ist es nicht möglich, dass Handle der Kamera direkt durchzuschleifen und auf die Zwischen-Pufferung im Byte-Array zu verzichten?
Gruss!