Cette question est au sujet de comment lire/écrire, de répartir et de gérer les données de pixels d'une image Bitmap.
Voici un exemple de la façon d'allouer un tableau d'octets (gestion de la mémoire) pour les données de pixel et la création d'un Bitmap de l'utiliser:
Size size = new Size(800, 600);
PixelFormat pxFormat = PixelFormat.Format8bppIndexed;
//Get the stride, in this case it will have the same length of the width.
//Because the image Pixel format is 1 Byte/pixel.
//Usually stride = "ByterPerPixel"*Width
//Mais il n'est pas toujours vrai. Plus d'info à bobpowell.
int stride = GetStride(size.Width, pxFormat);
byte[] data = new byte[stride * size.Height];
GCHandle handle = GCHandle.Alloc(data, GCHandleType.Pinned);
Bitmap bmp = new Bitmap(size.Width, size.Height, stride,
pxFormat, handle.AddrOfPinnedObject());
//After doing your stuff, free the Bitmap and unpin the array.
bmp.Dispose();
handle.Free();
public static int GetStride(int width, PixelFormat pxFormat)
{
//float bitsPerPixel = System.Drawing.Image.GetPixelFormatSize(format);
int bitsPerPixel = ((int)pxFormat >> 8) & 0xFF;
//Number of bits used to store the image data per line (only the valid data)
int validBitsPerLine = width * bitsPerPixel;
//4 bytes for every int32 (32 bits)
int stride = ((validBitsPerLine + 31) / 32) * 4;
return stride;
}
Je pensais que l'image serait de faire une copie du tableau de données, mais il en fait des points pour les mêmes données. A été vous pouvez le voir:
Color c;
c = bmp.GetPixel(0, 0);
Console.WriteLine("Color before: " + c.ToString());
//Prints: Color before: Color [A=255, R=0, G=0, B=0]
data[0] = 255;
c = bmp.GetPixel(0, 0);
Console.WriteLine("Color after: " + c.ToString());
//Prints: Color after: Color [A=255, R=255, G=255, B=255]
Questions:
Est-il sécuritaire de faire créer une image à partir d'un byte[] array (gestion de la mémoire) et free() le GCHandle? Si il n'est pas sûr, les Malades ont besoin de garder un épinglé tableau, comment le mauvais est que pour GC/Performance?
Est-il sécuritaire de modifier les données (ex: data[0] = 255;)?
L'adresse d'un Scan0 peut être modifié par le GC? Je veux dire, j'ai l'Scan0 d'un blocage bitmap, puis déverrouiller et après un certain temps de le verrouiller à nouveau, le Scan0 peut être différent?
Quel est le but de ImageLockMode.UserInputBuffer dans la méthode LockBits? Il est très difficile de trouver des infos à ce sujet! MSDN ne pas expliquer clairement!
EDIT 1: Certains de suivi
Vous avez besoin de garder épinglé. Il va ralentir la GC? Je lui ai demandé ici. Il dépend du nombre d'images et de ses dimensions. Personne ne l'ont m'a donné une réponse quantitative. Il paraît que c'est difficile à déterminer. Vous pouvez également affecter la mémoire à l'aide de Maréchal ou de l'utilisation de la mémoire non managée alloués par l'image Bitmap.
J'ai fait beaucoup de test à l'aide de deux fils. Tant que le Bitmap est verrouillé, il est ok. Si l'image est débloquer, qu'il n'est pas sûr! Mon poste sur lire/écrire directement à Scan0. Boing la réponse "je l'ai déjà expliqué plus haut pourquoi vous avez de la chance d'être en mesure d'utiliser scan0 à l'extérieur de la serrure. Parce que vous utilisez l'original bmp PixelFormat et que le RIB est optimisé dans ce cas, pour vous donner le pointeur et non une copie. Ce pointeur est valide jusqu'à l'OS va décider de le libérer. Le seul moment où il y a une garantie est entre LockBits et UnLockBits. Période."
Oui, ça peut arriver, mais les grandes régions de la mémoire sont traités différemment par le GC, il se déplace/libère de ce grand objet, moins fréquemment. Ainsi, il peut prendre un certain temps pour GC déplacer ce tableau. À partir de MSDN: "une allocation égale ou supérieure à
85,000 bytes
va sur l'large object heap (LOH)
" ... "LOH ne sont collectées pendant une collection de génération 2". .NET 4.5 a des Améliorations à LOH.Cette question ont été répondues par @Boing. Mais je vais l'admettre. Je n'ai pas la comprendre pleinement. Donc, si
Boing
ou quelqu'un d'autre pourrait -please clarify it
, je serais heureux. Par ailleurs, Pourquoi je ne peux pas directement en lecture/écriture à Sca0 sans verrouillage? Non, vous ne pouvez pas. Scan0 points à une copie des données de l'image faite par la mémoire non managée (à l'intérieur de GDI). Après le déblocage, cette mémoire peut être de réaffecter à d'autres trucs, ses garantis pas plus que Scan0 le réel des données Bitmap. Ce peut être reproduite à l'obtention de la Scan0 dans un de verrouiller, déverrouiller, et faire un peu tourner-flit dans la déverrouillé bitmap. Après un certain temps, Scan0 sera point à une défaillance de la région, et vous aurez une exception lorsque vous tentez de lire/écrire à son emplacement de mémoire.