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 LockBits
qui 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 Bitmap
bien 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
Vous devez vous connecter pour publier un commentaire.
Créer un image valide en-têteet preappend au tableau d'octets. Vous aurez seulement besoin de créer manuellement des 56-128 octets de données.
Deuxième, créer un flux à partir d'un tableau d'octets.
Prochaine, créer une image bitmap ou par la classe à l'aide de l'Image.FromStream()/Bitmap.FromStream()
Je ne peux pas imaginer qu'il y a toute sorte de matières premières fonctions d'imagerie .Net. Il ya tellement d'informations nécessaires pour une image, il serait extrêmement longue liste de paramètres pour une méthode d'accepter octets brutes et de créer une imaginer (c'est une image bitmap, jpeg, gif, png, etc, et toutes les autres données de chacun de ces exige de créer une image valide), il n'aurait plus de sens.
Essayer cette
Semble que tous vos appareils sont de même type, de sorte que les images données. Je ne sais pas si c'est possible dans votre cas, mais pourriez-vous créer un cette "plein de" image de n'importe quelle image et ensuite de simplement utiliser l'en-tête en tant que modèle (puisque ce sera le même pour toutes les images).