Bitmap im Speicher erstellen - wieder aufgegriffen



  • Hallo Profis,

    ich verwende Microsoft Visual C++ (Microsoft Developer Studio 2008) und lese mit Hilfe einer Windows Forms Anwendung aus einem CCD Bildsensor ein unsigned short int array aus, welches die Graustufen des Sensors als 16 Bit Werte (0 bis 65535) enthält.

    So ist das Array definiert:

    array<unsigned short int,2>^ imgarray = gcnew array<unsigned short int,2>(height,width);
    

    Ich möchte diese Bildinformation gern z.B. in einer pictureBox darstellen.
    Das funktioniert bisher so:

    Bitmap ^bmp = gcnew Bitmap(100,100);
    	int countw = 0;
    	int counth = 0;
    	int Color;
    	while(countw < 100) {
    		counth = 0;
    		while(counth < 100) {
    
    			Color = Convert::ToInt16(imgarray[countw*10,counth*10]*255/65535);
    			bmp->SetPixel(countw,counth, Color::FromArgb(255,Color,Color,Color));
    
    		counth++;
    		}
    	countw++;
    	}
    

    Das ist aber sehr unbefriedigend, da dies zu langsam läuft und um überhaupt in endlicher Zeit was zu sehen, nur etwa jeden 10 Punkt darstellt. Nun zu meiner Frage.
    Im Speicher liegt ja schon ein Array, welches eine 16bit Bitmap enthält vor. Schön wäre, wenn man den Bitmap Header einfach auch noch (davor) in den Speicher schreiben könnte und den gesamten Speicherbereich dann als Bitmap übergibt. Um einen Speicherbereich, der bereits die vollständige Bitmapinformation enthält in eine Bitmap umzuwandeln, könnte man vielleicht diesen Codeschnipsel verwenden (Quelle: http://www.c-plusplus.net/forum/viewtopic-var-t-is-192712.html)

    Drawing::Imaging::BitmapData^ myData; 
    System::Object^ buffer; 
    //hier müsste jetzt ein Speicherbereich übergeben warden 
    array<unsigned char>^ myBuffer=static_cast<array<unsigned char>^>(buffer);
    int buffersize; 
    Bitmap^ m_Bitmap = gcnew Drawing::Bitmap(height,width,Drawing::Imaging::PixelFormat::Format16bppGrayScale); 
    myData = m_Bitmap->LockBits(Drawing::Rectangle(0,0,m_Bitmap->Width,m_Bitmap->Height),Drawing::Imaging::ImageLockMode::WriteOnly,Drawing::Imaging::PixelFormat::Format24bppRgb); 
    System::Runtime::InteropServices::Marshal::Copy(myBuffer,40,myData->Scan0,buffersize-40); 
    m_Bitmap->UnlockBits(myData);
    

    Jedoch müsste buffer noch auf den modifizierten Speicherbreich zeigen.
    Vielleicht kennt sich ja jemand mit Speicheroperationen aus und kann mir einen Tipp geben, wie ich zum Ziel kommen könnte.

    MfG



  • Hallo Forum,

    nach längerem herumexperimentieren habe ich mich dazu entschlossen, dass es nicht möglich ist, mit den mir zur Verfügung stehenden Sprachmitteln im Speicher ein Bitmap „elegant“ zusammenzubauen.
    Jedoch habe ich unterdessen eine wesentlich schnellere Variante implementiert.
    Sie basiert allerdings immer noch darauf, dass jedes Byte einzeln umgedreht wird. Hier ist mal ein Codeschnipsel aus dem zugehörigem Projekt – nur falls jemand mal über ein ähnliches Problem stolpert:

    //ImageSampleTest
    //heigth und width sind die Spalten und Zeilen des CCD Sensors
    
    Bitmap ^bmp = gcnew Bitmap(height/2,width/2);
    
    //hier wird erstmal jeder Pixel mit herkömmlichen Mittel auf Black gesetzt 
    for (counth = 0; counth < bmp->Height; counth++ ) {
    		for (countw = 0; countw < bmp->Width; countw++ ) {	
    
    		bmp->SetPixel(countw,counth, Color::Black);
    		}
    	}
    
    int bytes = bmp->Width * bmp->Height * 4;
    int colval;
    
    IntPtr ptr;
    array<Byte>^rgbValues = gcnew array<Byte>(bytes);
    System::Drawing::Rectangle rect = System::Drawing::Rectangle(0,0,bmp->Width,bmp->Height);
    
    int counter;
    
    while(CCD_ON) {
    
    // an dieser Stelle befindet sich eigentlich eine Funktion, die imgarray 
    // mit SchwarzWeißdaten aus dem CCD Sensor überschreibt
    
    System::Drawing::Imaging::BitmapData^ bmpData = bmp->LockBits( rect, System::Drawing::Imaging::ImageLockMode::ReadWrite, bmp->PixelFormat );
       ptr = bmpData->Scan0;	
       System::Runtime::InteropServices::Marshal::Copy( ptr, rgbValues, 0, bytes );
    
    	countw = 0;
    	counth = 0;
    
       for (counter = 0; counter < rgbValues->Length; counter += 4 ){
    
    //jedes “bytequartet” im byte- array muss nun als Punkt identifiziert und // mit einem Farbwert versehen werden
    	   colval = imgarray[counth,countw]*255/4000;   
    
       counth += 2;
    	   if(counth > height-1) {
    		   counth = 0;
    		   countw += 2;
    	   }
    	   if(countw > width-1) countw = width-2;
    
    	  rgbValues[counter ] = colval;
    	  rgbValues[counter + 1] = colval;
    	  rgbValues[counter + 2] = colval;
       }
    
    System::Runtime::InteropServices::Marshal::Copy( rgbValues, 0, ptr, bytes );
       bmp->UnlockBits( bmpData );
    
    pictureBox1->Image = bmp;
    pictureBox1->Update();
    
    }
    

    Dieses Programmschnipsel stellt mit dem DualCore Rechner, auf dem es läuft ca. alle 1 ms ein neues Bild zur Verfügung. Warum die SetPixel Methode so langsam ist, ist mir allerdings nicht klar.

    MfG.


Log in to reply