Wie konvertieren Sie ein byte-array in eine Bitmap-Instanz (.NET)?

Arbeite ich mit Kameras (in diesem Fall schwarz-weiß) in VB.NET. Die API der Kameras ist in C++ und der Hersteller bietet Wrapper. Typisch ist in diesen Fällen das Bild zurück, wie eine Byte array. In meinem speziellen Fall sind es 8 bit pro pixel, es gibt also keine Lust bitpacking rückgängig zu machen.

War ich baff.NET hat so wenig Unterstützung für diese Art der Sache. Online-Suche, fand ich verschiedene Themen, aber es hilft nicht, dass in vielen Fällen haben Menschen ein byte-array entsprechend Bild Daten (Lesen Sie ein Bild-Datei in ein byte-array und dann haben .NET interpretieren Sie das array als eine Datei mit header und allem).

In diesem Fall muss ich ein array konvertieren von raw-pixel-Werte vor allem in etwas kann ich die Anzeige auf dem Bildschirm.

Scheint es nicht zu sein, eine integrierte Möglichkeit, dies zu tun, weil die 8 bit /Pixel-format eingebaut .NET indiziert ist (braucht eine palette), aber es scheint nicht, dass die Einstellung der Farbpalette unterstützt wird. Wieder, dies hat mich wirklich überrascht. Diese ist das vielversprechendste Thema, die ich gefunden.

Also die einzige Möglichkeit, die ich gefunden, dies zu tun ist, erstellen Sie eine Bitmap und dann kopieren Sie die pixel-Werte, pixel für pixel. In meinem Fall eine 8 MPixel Bild nahm mehrere Sekunden auf die Schnellste i7 beim Einsatz SetPixel.

Die alternative, die ich gefunden, um mit SetPixel ist LockBits, die dann gibt Ihnen Zugang zu den (unmanaged) array von bytes, stellt das Bild. Es scheint verschwenderisch, weil ich zum Bearbeiten des array .NETZ und kopieren Sie Sie dann zurück zu unmananaged Raum. Ich bin schon kopieren die ursprünglichen Bild Daten einmal (also das original kann wiederverwendet oder verworfen werden, indem der rest von dem, was vor sich geht), so zwar wesentlich schneller als mit SetPixel dies scheint immer noch verschwenderisch.

Hier ist der VB-code habe ich:

Public Function GetBitmap(ByRef TheBitmap As System.Drawing.Bitmap) As Integer
    Dim ImageData() As Byte
    Dim TheWidth, TheHeight As Integer
    'I've omitted the code here (too specific for this question) which allocates
    'ImageData and then uses Array.Copy to store a copy of the pixel values
    'in it. It also assigns the proper values to TheWidth and TheHeight.

    TheBitmap = New System.Drawing.Bitmap(TheWidth, TheHeight, System.Drawing.Imaging.PixelFormat.Format24bppRgb)
    Dim TheData As System.Drawing.Imaging.BitmapData = TheBitmap.LockBits(
        New System.Drawing.Rectangle(0, 0, TheWidth, TheHeight), Drawing.Imaging.ImageLockMode.ReadWrite, TheBitmap.PixelFormat)
    Dim Image24(Math.Abs(TheData.Stride) * TheHeight) As Byte
    'Then we have two choices: to do it in parallel or not. I tried both; the sequential version is commented out below.
    System.Threading.Tasks.Parallel.For(0, ImageData.Length, Sub(i)
                                                                 Image24(i * 3 + 0) = ImageData(i)
                                                                 Image24(i * 3 + 1) = ImageData(i)
                                                                 Image24(i * 3 + 2) = ImageData(i)
                                                             End Sub)
    'Dim i As Integer
    'For i = 0 To ImageData.Length - 1
    '    Image24(i * 3 + 0) = ImageData(i)
    '    Image24(i * 3 + 1) = ImageData(i)
    '    Image24(i * 3 + 2) = ImageData(i)
    'Next
    System.Runtime.InteropServices.Marshal.Copy(Image24, 0, TheData.Scan0, Image24.Length)
    TheBitmap.UnlockBits(TheData)

    'The above based on
    'http://msdn.microsoft.com/en-us/library/system.drawing.imaging.bitmapdata.aspx

    Return 1

End Function

Für eine 8-MPixel-Bild der sequenziellen version verbraucht etwa 220 Millisekunden von der Erstellung TheBitmap bis zu (und einschließlich) der Aufruf zu TheBitmap.UnlockBits(). Die parallele version ist viel mehr inkonsistent, aber im Bereich zwischen 60 und 80 Millisekunden. Bedenkt, dass ich bin, den Erwerb von vier Kameras gleichzeitig und streaming zur Festplatte mit viel Zeit zu ersparen, das ist ziemlich enttäuschend. Die API kommt mit Beispiel-code in C++ können die Anzeige von vier Kameras gleichzeitig bei voller Bildrate (17 fps). Es nie sich mit Bitmap natürlich, da GDI greift auf arrays von raw-pixel Werte.

In der Zusammenfassung, ich muss über das verwaltete/nicht verwaltete Hindernis einfach, weil es keinen direkten Weg, um ein array von pixel-Werten und "Zeug" in eine Bitmap Instanz. In diesem Fall bin ich auch kopieren Sie die pixel-Werte in ein 24bpp Bitmap weil ich kann "set" die palette in einem indizierten Bild also 8 bit /Pixel ist nicht sinnvoll, format für die Anzeige.

Gibt es keinen besseren Weg?

InformationsquelleAutor pelesl | 2012-04-18

Schreibe einen Kommentar