Comment convertir un tableau d'octets en une instance Bitmap (.NET)?

Je suis en train de travailler avec des caméras (dans ce cas monochrome) VB.NET. L'API des caméras est en C++ et le fabricant fournit wrappers. Comme souvent dans ces cas, l'image est retournée comme une Byte tableau. Dans mon cas particulier, il est à 8 bits par pixel, donc il n'y a pas de fantaisie bitpacking pour annuler.

J'ai été sidéré.NET a si peu de soutien pour ce type de chose. La recherche en ligne j'ai trouvé des sujets divers, mais il n'aide pas que, dans de nombreux cas, les gens ont un tableau d'octets correspondant à des données d'image (qui est, de lire un fichier d'image dans un tableau d'octets, puis ont .NET interpréter le tableau sous la forme d'un fichier, avec en-tête et tout et tout).

Dans ce cas j'ai besoin de convertir un tableau de valeurs de pixel brutes, en particulier, quelque chose que je peux afficher sur l'écran.

Il ne semble pas être intégrés dans la façon de le faire, parce que le 8bpp format construit .NET est indexé (besoin d'une palette), mais il ne semble pas que la définition de la palette est pris en charge. Encore une fois, cela m'a vraiment surpris. Cette est la plus prometteuse sujet que j'ai trouvé.

Donc le seul moyen que j'ai trouvé à faire c'est de créer une Bitmap puis copiez les valeurs de pixel pixel par pixel. Dans mon cas, un 8 Mégapixels, l'image a pris plusieurs secondes sur la manière la plus rapide i7 lors de l'utilisation de SetPixel.

L'alternative que j'ai trouvé à l'aide de SetPixel est LockBitsqui vous donne accès à la (non géré) tableau d'octets qui constitue l'image. Il semble inutile, parce que je dois manipuler le tableau .NET, puis la copier à unmananaged de l'espace. Je suis déjà la copie de l'image originale les données une seule fois (donc l'original peut être réutilisé ou rejetés par le reste de ce qu'il se passe) donc, bien que nettement plus rapide que l'utilisation SetPixel cela semble encore un gaspillage.

Voici le code en VB j'ai:

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

Pour un 8 Mpixels image de la version séquentielle consomme environ 220 millisecondes à partir de la création de TheBitmap jusqu'à (et y compris) l'appel à TheBitmap.UnlockBits(). La version parallèle est beaucoup plus instable mais varie entre 60 et 80 millisecondes. Étant donné que je suis l'acquisition à partir de quatre caméras simultanément et en continu sur le disque avec beaucoup de temps à perdre, c'est assez décevant. L'API est livré avec des exemples de code en C++ qui permet l'affichage de tous les quatre caméras simultanément à pleine cadence (17 fps). Il ne traite jamais avec Bitmapbien sûr, depuis GDI accède à des tableaux de valeurs de pixel brutes.

En résumé, je voyage à travers les sites gérés et non gérés barrière simplement parce qu'il n'y a aucun moyen direct pour prendre un tableau de valeurs de pixel et de "trucs" dans un Bitmap instance. Dans ce cas, je suis aussi de copier les valeurs des pixels dans une 24bpp Bitmap parce que je ne peux pas "set", la palette d'une image indexée, donc 8bpp n'est pas viable format pour l'affichage.

Il n'y a pas de meilleure façon?

source d'informationauteur pelesl