2013-04-21 14 views
6

ho Lista pixel in questo formatodati pixel per immagine

ArrayList list = new ArrayList(); 
list.add(Red); 
list.add(Blue); 
list.add(Green); 

Ho molti valori come questo. Voglio convertire la lista degli array in immagine. Ho provato molto ma non ho trovato materiale adeguato.

EDIT: Questo può aiuta:

List<byte> pic = new List<byte>(); 
for (int j = 0; j < headdata.Count; j++) 
{ 
    if(headdata.ElementAt(j).getHead() == i) 
    { 
     pic.Add((byte)headdata.ElementAt(j).getRed()); 
     pic.Add((byte)headdata.ElementAt(j).getGreen()); 
     pic.Add((byte)headdata.ElementAt(j).getBlue()); 
    } 
} 
+0

Perché stai utilizzando ArrayList per archiviare i dati dei pixel? –

+0

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

+0

Qual è il tuo tipo di progetto? 'WPF',' Windows Form', ... –

risposta

4

Prima di tutto, come ho detto nel commento, sarebbe meglio usare Lista invece di ArrayList per evitare la boxe/unboxing.

Quindi, è necessario BPP (bit per pixel) e la larghezza e altezza per creare un'immagine.

se si dispone di tutti questi valori, allora si può ottenere iniziare indice di pixel:

int i = ((y * Width) + x) * (depth/8); 

Ad esempio:

List<byte> bytes = new List<byte>(); // this list should be filled with values 
    int width = 100; 
    int height = 100; 
    int bpp = 24; 

    Bitmap bmp = new Bitmap(width, height); 

    for (int y = 0; y < height; y++) 
    { 
     for (int x = 0; x < width; x++) 
     { 
      int i = ((y * width) + x) * (bpp/8); 
      if(bpp == 24) // in this case you have 3 color values (red, green, blue) 
      { 
       // first byte will be red, because you are writing it as first value 
       byte r = bytes[i]; 
       byte g = bytes[i + 1]; 
       byte b = bytes[i + 2]; 
       Color color = Color.FromArgb(r, g, b); 
       bmp.SetPixel(x, y, color); 
      } 

     } 
    } 

È possibile utilizzare altre librerie per creare bitmap e scrivere i valori più velocemente. (SetPixel() è molto lento. See)

+0

Molto utile, grazie – greatmajestics

8

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.

+0

Nota: è necessario includere 'utilizzando System.Runtime.InteropServices;' nella parte superiore del file affinché funzioni. – starbeamrainbowlabs

+0

Oh e hai bisogno di usare System.Drawing.Imaging; – starbeamrainbowlabs

+0

Grazie, aggiornato per chiarire. –

Problemi correlati