2010-02-15 18 views
46

Esiste un modo per convertire un'immagine in scala di grigi a 16 pixel per bit, anziché impostare ciascuno dei componenti r, g eb nella luminanza. Al momento ho un bmp dal file.Converti un'immagine in scala di grigi

Bitmap c = new Bitmap("filename"); 

Voglio una bitmap d, che è la versione in scala di grigi di c. Vedo un costruttore che include System.Drawing.Imaging.PixelFormat, ma non capisco come usarlo. Sono nuovo di Image Processing e delle relative librerie C#, ma ho un'esperienza moderata con C# stesso.

Qualsiasi aiuto, riferimento a una fonte online, suggerimento o suggerimento sarà apprezzato.

Grazie.

MODIFICA: d è la versione in scala di grigi di c.

risposta

56

"Voglio una bitmap d, che è in scala di grigi. faccio vedere un consructor che include System.Drawing.Imaging.PixelFormat, ma non capisco come usare questo".

Ecco come fare questo

Bitmap grayScaleBP = new 
     System.Drawing.Bitmap(2, 2, System.Drawing.Imaging.PixelFormat.Format16bppGrayScale); 

EDIT: Per convertire in in scala di grigi

   Bitmap c = new Bitmap("fromFile"); 
      Bitmap d; 
      int x, y; 

      // Loop through the images pixels to reset color. 
      for (x = 0; x < c.Width; x++) 
      { 
       for (y = 0; y < c.Height; y++) 
       { 
        Color pixelColor = c.GetPixel(x, y); 
        Color newColor = Color.FromArgb(pixelColor.R, 0, 0); 
        c.SetPixel(x, y, newColor); // Now greyscale 
       } 
      } 
      d = c; // d is grayscale version of c 

più veloce versione da switchonthecode seguente link per un'analisi completa:

public static Bitmap MakeGrayscale3(Bitmap original) 
{ 
    //create a blank bitmap the same size as original 
    Bitmap newBitmap = new Bitmap(original.Width, original.Height); 

    //get a graphics object from the new image 
    Graphics g = Graphics.FromImage(newBitmap); 

    //create the grayscale ColorMatrix 
    ColorMatrix colorMatrix = new ColorMatrix(
     new float[][] 
     { 
     new float[] {.3f, .3f, .3f, 0, 0}, 
     new float[] {.59f, .59f, .59f, 0, 0}, 
     new float[] {.11f, .11f, .11f, 0, 0}, 
     new float[] {0, 0, 0, 1, 0}, 
     new float[] {0, 0, 0, 0, 1} 
     }); 

    //create some image attributes 
    ImageAttributes attributes = new ImageAttributes(); 

    //set the color matrix attribute 
    attributes.SetColorMatrix(colorMatrix); 

    //draw the original image on the new image 
    //using the grayscale color matrix 
    g.DrawImage(original, new Rectangle(0, 0, original.Width, original.Height), 
     0, 0, original.Width, original.Height, GraphicsUnit.Pixel, attributes); 

    //dispose the Graphics object 
    g.Dispose(); 
    return newBitmap; 
} 
+0

Mi dispiace, avrei dovuto dire che nella mia domanda voglio la versione in scala di grigi della mia bitmap originale. Ho modificato il post per riflettere questo. – 0fnt

+11

Questo metodo (pixel per pixel è troppo lento) controlla questo articolo qui: http: //www.switchonthecode.com/tutorials/csharp-tutorial-convert-a-color-image-to-grayscale – Luis

+6

Inoltre, il pixel-by il metodo -pixel utilizzava solo il valore Rosso .... – mpen

27
Bitmap d = new Bitmap(c.Width, c.Height); 

for (int i = 0; i < c.Width; i++) 
{ 
    for (int x = 0; x < c.Height; x++) 
    { 
     Color oc = c.GetPixel(i, x); 
     int grayScale = (int)((oc.R * 0.3) + (oc.G * 0.59) + (oc.B * 0.11)); 
     Color nc = Color.FromArgb(oc.A, grayScale, grayScale, grayScale); 
     d.SetPixel(i, x, nc); 
    } 
} 

In questo modo mantiene anche il canale alfa.
Divertiti.

+4

Perché ho ricevuto un downvote? Questa risposta è perfettamente OK e sull'argomento. – Vercas

+1

So che è una vecchia risposta, ma potresti approfondire le costanti che moltiplica sui valori R, G, B? Vedo che riassume "1.0", ma c'è qualche spiegazione sul perché? –

+3

@LarsKristensen Vedi questo: https://en.wikipedia.org/wiki/Grayscale – lukegravitt

6

Nessuno degli esempi precedenti crea immagini bitmap a 8 bit (8 bpp). Alcuni software, come l'elaborazione delle immagini, supportano solo 8bpp. Sfortunatamente le librerie MS .NET non hanno una soluzione. Il formato PixelFormat.Format8bppIndexed sembra promettente, ma dopo molti tentativi non sono riuscito a farlo funzionare.

Per creare un vero file bitmap a 8 bit è necessario creare lo proper headers. Alla fine ho trovato la soluzione Grayscale library per la creazione di file bitmap (BMP) a 8 bit. Il codice è molto semplice:

Image image = Image.FromFile("c:/path/to/image.jpg"); 
GrayBMP_File.CreateGrayBitmapFile(image, "c:/path/to/8bpp/image.bmp"); 

Il codice per questo progetto è ben lungi dall'essere abbastanza, ma funziona, con un piccolo problema semplice da-fix. L'autore ha hardcoded la risoluzione dell'immagine a 10x10. I programmi di elaborazione delle immagini non sono così. La correzione è aperta GrayBMP_File.cs (sì, nome file funky, lo so) e sostituire le righe 50 e 51 con il codice sottostante. L'esempio imposta la risoluzione su 200x200 ma dovresti cambiarlo al numero corretto.

int resX = 200; 
int resY = 200; 
// horizontal resolution 
Copy_to_Index(DIB_header, BitConverter.GetBytes(resX * 100), 24); 
// vertical resolution 
Copy_to_Index(DIB_header, BitConverter.GetBytes(resY * 100), 28); 
+0

Vorrei testarlo e upvotare, ma in poco tempo. Grazie per la risposta però. – 0fnt

+0

il trucco con 8bpp è che è necessario modificare l'array interno raw che supporta l'immagine. Puoi ottenerlo chiamando 'image.LockBits()' e poi copiare/inserire i dati usando 'Marshal.Copy'. Google per ottenere l'intero processo. Si noti che la falcata di un'immagine (una riga letta dai dati) è spesso più lunga della larghezza effettiva, poiché viene arrotondata al multiplo più vicino di 4 byte. – Nyerguds

6

In sintesi alcuni elementi qui: Ci sono alcune opzioni di pixel-by-pixel che, pur essendo semplice, basta non sono veloci.

Il commento di @Luis che collega a: (archiviato) https://web.archive.org/web/20110827032809/http://www.switchonthecode.com/tutorials/csharp-tutorial-convert-a-color-image-to-grayscale è superbo.

Esegue tre diverse opzioni e include tempi per ciascuna.

+3

Il terzo esempio nel link sopra è super efficiente e risolve direttamente il mio problema – ford

+0

Purtroppo quel collegamento è morto ... –

+3

@RichardEverett In effetti. Archivio Web in soccorso! Fisso. – jeffreypriebe

3

Il codice sotto è la soluzione più semplice:

Bitmap bt = new Bitmap("imageFilePath"); 

for (int y = 0; y < bt.Height; y++) 
{ 
    for (int x = 0; x < bt.Width; x++) 
    { 
     Color c = bt.GetPixel(x, y); 

     int r = c.R; 
     int g = c.G; 
     int b = c.B; 
     int avg = (r + g + b)/3; 
     bt.SetPixel(x, y, Color.FromArgb(avg,avg,avg)); 
    } 
} 

bt.Save("d:\\out.bmp"); 
9

C'è un metodo statico in ToolStripRenderer classe, denominata CreateDisabledImage. Il suo utilizzo è semplice come:

Bitmap c = new Bitmap("filename"); 
Image d = ToolStripRenderer.CreateDisabledImage(c); 

Esso utilizza una matrice diversa po 'da quello in risposta accettata e inoltre lo moltiplica per una trasparenza del valore di 0,7, quindi l'effetto è leggermente diverso di una semplice scala di grigi, ma se vuoi solo rendere grigia l'immagine, è la soluzione più semplice e migliore.

+2

Oh amico, grazie per questo. Ciò corrisponde all'aspetto delle immagini all'interno dei controlli disabilitati in WinForms, il che mantiene tutto in modo coerente. – Jimmy

Problemi correlati