Travail rapide avec les Bitmaps en C#
J'ai besoin d'accéder à chaque pixel d'une image Bitmap, travailler avec eux, puis de les enregistrer dans un fichier Bitmap.
À l'aide de Bitmap.GetPixel()
et Bitmap.SetPixel()
, mon programme s'exécute lentement.
Comment puis-je convertir rapidement Bitmap
à byte[]
et à l'arrière?
J'ai besoin d'un byte[]
avec length = (4 * width * height)
, contenant RGBA données de chaque pixel.
- Lien suivant contient un pixel bitmap méthodes d'accès relativement. csharpexamples.com/fast-image-processing-c
Vous devez vous connecter pour publier un commentaire.
Vous pouvez faire un couple de différentes manières. Vous pouvez utiliser
unsafe
, l'accès direct aux données, ou vous pouvez utiliser marshaling pour copier les données d'avant en arrière. Le code unsafe est plus rapide, mais marshaling ne nécessite pas de code non sécurisé. Voici un comparaison des performances j'ai fait un tout à l'arrière.Voici un exemple complet d'utilisation de lockbits:
Ici est la même chose, mais avec marshaling:
bData.Height
permettra d'accélérer les choses, parce que vous êtes seulement en prenant le premier rang de vos données. Essayezsize = 1
qui va rendre les choses encore plus vite!bData.Stride
ne doit pas être égal àb.Width * bytePerPix
.width * BPP / 8
de cours) * hauteur de la longueur. Pour les images avec des <8bpp cependant, les choses deviennent... intéressant. Une bonne règle est de toujours inclure la foulée avec vos fonctions de traitement d'image, de préférence en tant que paramètre de référence dans le cas où il est changé pour votre sortie.GetBitsPerPixel()
ici?System.Drawing.Bitmap.GetPixelFormatSize(...);
Vous pouvez utiliser Bitmap.LockBits méthode. Aussi, si vous souhaitez utiliser en parallèle de l'exécution de la tâche, vous pouvez utiliser la classe Parallèle dans le Système.Le filetage.Les tâches de l'espace de noms. Liens suivants sont quelques exemples et des explications.
Vous voulez LockBits. Vous pouvez ensuite extraire les octets que vous voulez à partir de l'objet BitmapData il vous donne.
BitmapData
objet renvoyé de LockBits à l'intérieur d'ununsafe
bloc avec un pointeur de cast (NOTE: en fait, je n'ai aucune idée de si c'est plus rapide ou pas, mais je suis en train de provoquer quelqu'un d'autre dans l'analyse comparative il).Bâtiment sur @notJim réponse (et avec l'aide de http://www.bobpowell.net/lockingbits.htm), j'ai développé ci-après qui me rend la vie beaucoup plus facile en qui je me retrouve avec un tableau de tableaux qui me permet de sauter à un pixel par
x
ety
coordonnées. Bien sûr, lax
de coordonnées doit être corrigé par le nombre d'octets par pixel, mais c'est une extension facile.Il y a une autre façon qui est plus rapide et beaucoup plus pratique. Si vous avez un coup d'oeil à l'image Bitmap constructeurs, vous trouverez celui qui prend et IntPtr comme le dernier paramètre. Que IntPtr est pour la tenue de données de pixels. Alors, comment utilisez-vous?
Ce que vous avez maintenant, c'est un simple tableau d'Entiers et une image Bitmap référence à la même mémoire. Toutes les modifications apportées au tableau d'Entiers seront affectant directement l'image Bitmap. Laissez-nous essayer cela avec une luminosité simple à transformer.
Vous pouvez remarquer que j'ai utilisé une petite astuce pour éviter de faire un calcul en virgule flottante à l'intérieur de la boucle. Cela améliore les performances tout à fait un peu.
Et lorsque vous avez terminé, vous devez nettoyer un peu, bien sûr...
Que j'ai ignoré la composante alpha ici, mais vous êtes libre de l'utiliser ainsi. J'ai jeté ensemble beaucoup de bitmap outils d'édition de cette façon. Il est beaucoup plus rapide et plus fiable que le Bitmap.LockBits() et le meilleur de tous, il ne nécessite aucun mémoire de la copie de commencer le montage de votre image bitmap.
Essayer cette solution C#.
Créer une application winforms pour les tests.
Ajouter un Bouton et une PictureBox, et cliquez sur l'événement et une forme de clôture de l'événement.
Utiliser le code suivant pour votre forme:
Maintenant, les modifications que vous apportez à la matrice sera automatiquement mise à jour le Bitmap.
Vous aurez besoin d'appeler la méthode refresh sur la picturebox pour voir ces changements.