Aggiornamento
Ho pensato di migliorare questo post per riferimento futuro.
È molto più semplice se i dati dei pixel sono archiviati come array di numeri interi a 32 bit (idealmente senza segno). I 4 byte di ciascun numero intero devono corrispondere rispettivamente ai canali alfa, rosso, verde e blu. Se non stai utilizzando il canale alfa, mantienilo vuoto.
// If your image is always going to be the same size, make these constant -
// it speeds things up tremendously.
var width = 640;
var height = 480;
// Create the array to contain bitmap's pixel data.
// Making the pixels unsigned *can* speed up certain arithmetic operations,
// so use them if you're going to be manipulating colours as integers in the array.
// Note that array size is width * height only.
var pixels = new uint[width * height];
/* <Perform array operations here> */
// Create a handle to the object on the heap.
// Making it 'Pinned' prevents the GC from moving it around in memory.
var gchPixels = GCHandle.Alloc(pixels, GCHandleType.Pinned);
// Create the bitmap itself.
// Note: if you plan on making use of the alpha channel, make sure you use
// Format32bppArgb instead (no P).
// Format32bppPArgb means that the alpha channel is present but should be ignored.
var bitmap = new Bitmap(width, height, width * sizeof(uint),
PixelFormat.Format32bppPArgb,
gchPixels.AddrOfPinnedObject());
/* <Perform bitmap operations here> */
// Free the handle to stop the GC from pinning the array.
// This is important if you were dealing with a large array.
gchPixels.Free();
È possibile creare il proprio metodo per l'impostazione di un pixel ad una certa coordinata:
public void SetPixel(int x, int y, uint colour) => pixels[x + y * width] = colour;
Come starbeamrainbowlabs sottolineato:
GCHandle
, Bitmap
, e PixelFormat
si trovano in System.Runtime.InteropServices
, System.Drawing
e System.Drawing.Imaging
rispettivamente.
risposta originale Sotto
C'è piuttosto un buon modo di fare questo, ma richiede l'utilizzo di un array o byte al contrario di una lista.
Considerate questo:
// Define the width and the height of the image
int width = 100,
height = 100;
/* Create an array of bytes consisting of the area's worth of pixels
* with 3 bytes of data each.
*/
byte[] pixels = new byte[width * height * 3];
/* > Code for making the image etc. here < */
// Create our bitmap.
/* GCHandle requires System.Runtime.InteropServices
* PixelFormat requires System.Drawing.Imaging.
*/
Bitmap bmp = new Bitmap(width, height, width * 3, PixelFormat.Format24bppRgb,
GCHandle.Alloc(pixels, GCHandleType.Pinned).AddrOfPinnedObject());
Se si vuole cambiare questo per essere ARGB, è sufficiente modificare tutte le istanze di '3' con '4', e utilizzare PixelFormat.Format32bppArgb.
Come ho detto, questo richiede che si utilizzi un array anziché un elenco, ma questo non dovrebbe essere troppo difficile purché si conosca la larghezza e l'altezza dell'immagine. Un buon modo di impostare un singolo pixel nella matrice è (forse rendere un metodo per questo):
pixels[x + y * width] = R;
pixels[x + y * width + 1] = G;
pixels[x + y * width + 2] = B;
Questo metodo è in genere abbastanza veloce anche se questo è affatto necessario per qualsiasi cosa tu sei fare .
Fonte: esperienza.
Perché stai utilizzando ArrayList per archiviare i dati dei pixel? –
Sto raggruppando l'immagine, quindi non conosco le dimensioni esatte del cluster di immagini dall'inizio, se eseguo il ciclo una volta su dataset di grandi dimensioni ci vuole un po 'di tempo .. quindi sto usando l'arraylist per l'allocazione dinamica – greatmajestics
Qual è il tuo tipo di progetto? 'WPF',' Windows Form', ... –