2012-02-07 10 views
56

Voglio convertire un array di byte in un'immagine.Da matrice a immagine a conversione di immagini

Questo è il mio codice del database da cui ricevo l'array di byte:

public void Get_Finger_print() 
{ 
    try 
    { 
     using (SqlConnection thisConnection = new SqlConnection(@"Data Source=" + System.Environment.MachineName + "\\SQLEXPRESS;Initial Catalog=Image_Scanning;Integrated Security=SSPI ")) 
     { 
      thisConnection.Open(); 
      string query = "select pic from Image_tbl";// where Name='" + name + "'"; 
      SqlCommand cmd = new SqlCommand(query, thisConnection); 
      byte[] image =(byte[]) cmd.ExecuteScalar(); 
      Image newImage = byteArrayToImage(image); 
      Picture.Image = newImage; 
      //return image; 
     } 
    } 
    catch (Exception) { } 
    //return null; 
} 

Il mio codice di conversione:

public Image byteArrayToImage(byte[] byteArrayIn) 
{ 
    try 
    { 
     MemoryStream ms = new MemoryStream(byteArrayIn,0,byteArrayIn.Length); 
     ms.Write(byteArrayIn, 0, byteArrayIn.Length); 
     returnImage = Image.FromStream(ms,true);//Exception occurs here 
    } 
    catch { } 
    return returnImage; 
} 

Quando raggiungo la linea con un commento, la seguente eccezione si è verificato: Parameter is not valid.

Come posso risolvere ciò che causa questa eccezione?

+0

Hai controllato che i byte di immagine nella tua query siano validi? Potresti fare un File.WriteAllBytes ("myimage.jpg", byteArrayIn) per verificare. – Holstebroe

risposta

4

prova (UPDATE)

MemoryStream ms = new MemoryStream(byteArrayIn,0,byteArrayIn.Length); 
ms.Position = 0; // this is important 
returnImage = Image.FromStream(ms,true); 
+0

Grazie ma non risolto il problema da questo codice –

+2

Non ha molto senso scrivere l'array di byte nel flusso di memoria dopo che è stato inizializzato con lo stesso array di byte. In realtà non sono sicuro che MemoryStream permetta di scrivere oltre la lunghezza specificata nel costruttore. – Holstebroe

+0

@TanzeelurRahman vedere la mia risposta modificata ... – Yahia

70

si sta scrivendo per il vostro flusso di memoria due volte, anche non si disporre il flusso dopo l'uso. Si sta chiedendo anche al decodificatore di immagini di applicare la correzione del colore incorporato.

Prova a modificare:

using (var ms = new MemoryStream(byteArrayIn)) 
{ 
    return Image.FromStream(ms); 
} 
+0

È anche possibile rendere esplicito il flusso di memoria non scrivibile dopo l'inizializzazione: nuovo MemoryStream (byteArrayIn, false) – Holstebroe

+0

Nessun codice non risolto Problema –

+19

Questo viola una specifica in MSDN per Image .FromStream(), dove dice "Devi mantenere lo stream aperto per tutta la vita dell'immagine". Vedi anche http://stackoverflow.com/questions/3290060/getting-an-image-object-from-a-byte-array – RenniePet

2

Questo si ispira la risposta di Holstebroe, oltre a commenti qui: Getting an Image object from a byte array

Bitmap newBitmap; 
using (MemoryStream memoryStream = new MemoryStream(byteArrayIn)) 
    using (Image newImage = Image.FromStream(memoryStream)) 
     newBitmap = new Bitmap(newImage); 
return newBitmap; 
55

forse mi manca qualcosa, ma per me questo one-liner funziona bene con una matrice di byte che contiene un'immagine di un file JPEG.

Image x = (Bitmap)((new ImageConverter()).ConvertFrom(jpegByteArray)); 

EDIT:

Vedi qui per una versione aggiornata di questa risposta: How to convert image in byte array

+0

Ottimo ... tempo risparmiato – PawanS

+0

AAAh grazie, Finalmente una buona risposta. Perché così tante risposte con lo streaming di memoria, mi causano così tanti problemi. molte grazie ! – Julian50

+0

Buona risposta! questo può essere utilizzato in una funzione separata mentre tutte le altre proposte che utilizzano MemoryStream non possono (Stream deve essere tenuto aperto per tutta la durata dell'immagine) –

0

La maggior parte del tempo in cui questo accade è dati errati nella colonna SQL. Questo è il modo corretto di inserire in una colonna di immagine:

INSERT INTO [TableX] (ImgColumn) VALUES (
(SELECT * FROM OPENROWSET(BULK N'C:\....\Picture 010.png', SINGLE_BLOB) as tempimg)) 

La maggior parte delle persone lo fanno in modo non corretto in questo modo:

INSERT INTO [TableX] (ImgColumn) VALUES ('C:\....\Picture 010.png')) 
0

Hi provare il link qui sotto per me anche avuto lo stesso problema e mi sono risolto provare il link riportato in basso sarà aiuta u enter link description here

2

non hai dichiarato returnImage come qualsiasi tipo di variabile :)

Questo dovrebbe aiutare:

public Image byteArrayToImage(byte[] byteArrayIn) 
{ 
    try 
    { 
     MemoryStream ms = new MemoryStream(byteArrayIn,0,byteArrayIn.Length); 
     ms.Write(byteArrayIn, 0, byteArrayIn.Length); 
     Image returnImage = Image.FromStream(ms,true); 
    } 
    catch { } 
    return returnImage; 
} 
+1

utile come idea, ma ovviamente non funzionerà come scritto. returnImage deve essere dichiarato al di fuori della sezione try/catch. Anche returnImage deve essere istanziato in 'catch' - creo un singolo pixel bitmap: var image = new Bitmap (1, 1); Streaming memoria = nuovo MemoryStream(); image.Save (stream, ImageFormat.Jpeg); stream.Position = 0; – Reid

4

Tutte le risposte presentate presuppongono che la matrice di byte contenga dati in una rappresentazione di formato di file noto, come: gif, png o jpg. Ma recentemente ho avuto un problema nel tentativo di convertire byte[] s, contenente informazioni BGRA linearizzate, in modo efficiente negli oggetti Image. Il seguente codice lo risolve usando un oggetto Bitmap.

using System.Drawing; 
using System.Drawing.Imaging; 
using System.Runtime.InteropServices; 
public static class Extensions 
{ 
    public static Image ImageFromRawBgraArray(
     this byte[] arr, int width, int height) 
    { 
     var output = new Bitmap(width, height); 
     var rect = new Rectangle(0, 0, width, height); 
     var bmpData = output.LockBits(rect, 
      ImageLockMode.ReadWrite, output.PixelFormat); 
     var ptr = bmpData.Scan0; 
     Marshal.Copy(arr, 0, ptr, arr.Length); 
     output.UnlockBits(bmpData); 
     return output; 
    } 
} 

Questo è un po 'di variazione di una soluzione che è stato pubblicato il this site.

+0

come riferimento MSDN: Bitmap (Int32, Int32): "Questo costruttore crea una bitmap con un valore di enumerazione PixelFormat di Format32bppArgb.", Che significa che il byte [0] è blu, il byte [1] è verde, il byte [2] è rosso, byte [3] è alfa, byte [4] è blu e così via. – brk

6
public Image byteArrayToImage(byte[] bytesArr) 
{ 
    MemoryStream memstr = new MemoryStream(bytesArr); 
    Image img = Image.FromStream(memstr); 
    return img; 
} 
+0

Anche se normalmente non è una buona idea, inserisco un GC.Collect() prima del flusso di memoria. Stavo per esaurire la memoria quando ho caricato in memoria un sacco di file grafici di grandi dimensioni come i toearrays e li ho trasformati in immagini durante la visualizzazione. – Kayot

6

Mi piacerebbe notare che c'è un errore nella soluzione fornita da @ isaias-b.

Questa soluzione presuppone che stride sia uguale alla lunghezza della riga. Ma non è sempre vero. A causa degli allineamenti di memoria eseguiti da GDI, lo stride può essere maggiore della lunghezza della riga. Questo deve essere preso in considerazione. Altrimenti verrà generata un'immagine spostata non valida. I byte di riempimento in ogni riga verranno ignorati.

Il passo è la larghezza di una singola riga di pixel (una linea di scansione), arrotondata a un limite di quattro byte.

codice fisso:

using System.Drawing; 
using System.Drawing.Imaging; 
using System.Runtime.InteropServices; 

public static class ImageExtensions 
{ 
    public static Image ImageFromRawBgraArray(this byte[] arr, int width, int height, PixelFormat pixelFormat) 
    { 
     var output = new Bitmap(width, height, pixelFormat); 
     var rect = new Rectangle(0, 0, width, height); 
     var bmpData = output.LockBits(rect, ImageLockMode.ReadWrite, output.PixelFormat); 

     // Row-by-row copy 
     var arrRowLength = width * Image.GetPixelFormatSize(output.PixelFormat)/8; 
     var ptr = bmpData.Scan0; 
     for (var i = 0; i < height; i++) 
     { 
      Marshal.Copy(arr, i * arrRowLength, ptr, arrRowLength); 
      ptr += bmpData.Stride; 
     } 

     output.UnlockBits(bmpData); 
     return output; 
    } 
} 

Per illustrare ciò può portare a, diciamo generare PixelFormat.Format24bppRgb gradienti immagine 101x101:

var width = 101; 
var height = 101; 
var gradient = new byte[width * height * 3 /* bytes per pixel */]; 
for (int i = 0, pixel = 0; i < gradient.Length; i++, pixel = i/3) 
{ 
    var x = pixel % height; 
    var y = (pixel - x)/width; 
    gradient[i] = (byte)((x/(double)(width - 1) + y/(double)(height - 1))/2d * 255); 
} 

Se copieremo intero array così com'è per affrontare appuntita per bmpData.Scan0, otterremo l'immagine seguente. Spostamento dell'immagine perché parte dell'immagine è stata scritta in byte di riempimento, che è stata ignorata. Anche per questo motivo ultima riga è incompleta:

stride ignored

Ma se copieremo riga per riga spostamento puntatore destinazione bmpData.Stride valore, immaginata valido si genera:

stride taken into account

Anche Stride può essere negativo:

Se il passo è positivo, la bitmap è top-down. Se la falcata è negativa, la bitmap è dal basso verso l'alto.

Ma non ho lavorato con tali immagini e questo va oltre la mia nota.

risposta correlati: C# - RGB Buffer from Bitmap different from C++

-2

Ho trovato questo ragazzi Convert array to image

 private void button1_Click(object sender, EventArgs e) 
    { 
     try 
     { 
      string hasil = "D:\\coba1000.jpg"; 
      System.IO.File.WriteAllBytes(@hasil, bytestosend); 


      pictureBox1.ImageLocation = @hasil; 
     } 
     catch { } 
    } 
0

c'è approccio semplice, come di seguito, è possibile utilizzare il metodo FromStream di immagine per fare il trucco, Basta ricordarsi di utilizzare System .Disegno;

// using image object not file 
public byte[] imageToByteArray(Image imageIn) 
{ 
MemoryStream ms = new MemoryStream(); 
imageIn.Save(ms,System.Drawing.Imaging.ImageFormat.Gif); 
return ms.ToArray(); 
} 

public Image byteArrayToImage(byte[] byteArrayIn) 
{ 
MemoryStream ms = new MemoryStream(byteArrayIn); 
Image returnImage = Image.FromStream(ms); 
return returnImage; 
}