Conversión de matriz de bytes a la imagen

Quiero convertir una matriz de bytes a una imagen.

Este es el código de mi base de datos desde donde obtengo la matriz de bytes:

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; } 

Mi código de conversión:

 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; } 

Cuando llego a la línea con un comentario, ocurre la siguiente excepción: El Parameter is not valid.

¿Cómo puedo solucionar lo que está causando esta excepción?

Está escribiendo en su secuencia de memoria dos veces, y no está eliminando la secuencia después de su uso. También le está pidiendo al decodificador de imágenes que aplique una corrección de color incrustada.

Pruebe esto en su lugar:

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

Tal vez me falta algo, pero para mí este one-liner funciona bien con una matriz de bytes que contiene una imagen de un archivo JPEG.

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

EDITAR:

Vea aquí una versión actualizada de esta respuesta: Cómo convertir imágenes en matriz de bytes

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

Me gustaría señalar que hay un error en la solución proporcionada por @ isaias-b.

Esa solución asume que la stride es igual a la longitud de la fila. Pero no siempre es verdad. Debido a las alineaciones de memoria realizadas por GDI, la zancada puede ser mayor que la longitud de la fila. Esto debe ser tenido en cuenta. De lo contrario, se generará una imagen desplazada no válida. Los bytes de relleno en cada fila serán ignorados.

La zancada es el ancho de una sola fila de píxeles (una línea de exploración), redondeada a un límite de cuatro bytes.

Código fijo:

 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; } } 

Para ilustrar a qué puede conducir, PixelFormat.Format24bppRgb imagen de degradado PixelFormat.Format24bppRgb 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); } 

Si copiamos toda la matriz como está a la dirección apuntada por bmpData.Scan0 , obtendremos la siguiente imagen. La imagen se desplazó porque parte de la imagen se escribió en bytes de relleno, que se ignoró. También es por eso que la última fila está incompleta:

paso ignorado

Pero si copiamos el puntero de destino de desplazamiento fila por fila mediante el valor bmpData.Stride , se generará una imagen válida:

paso tomado en cuenta

Stride también puede ser negativo:

Si la zancada es positiva, el bitmap es de arriba hacia abajo. Si la zancada es negativa, el bitmap es de abajo hacia arriba.

Pero no trabajé con esas imágenes y esto está más allá de mi nota.

Respuesta relacionada: C # - RGB Buffer from Bitmap diferente de C ++

Todas las respuestas presentadas asumen que la matriz de bytes contiene datos en una representación de formato de archivo conocida, como: gif, png o jpg. Pero recientemente tuve un problema al intentar convertir byte[] s, que contiene información lineal de BGRA, de manera eficiente en objetos de Image . El siguiente código lo resuelve usando un objeto 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; } } 

Esta es una variación leve de una solución que se publicó en este sitio .

intente (ACTUALIZAR)

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

hay un enfoque simple como el siguiente, puedes usar el método de imagen FromStream para hacer el truco, solo recuerda usar System.Drawing;

 // 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; } 

No has declarado returnImage como ningún tipo de variable 🙂

Esto debería ayudar:

 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; } 

Esto está inspirado en la respuesta de Holstebroe, más comentarios aquí: Obtener un objeto de imagen de una matriz de bytes

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

La mayoría de las veces, cuando sucede esto, son datos incorrectos en la columna SQL. Esta es la forma correcta de insertar en una columna de imagen:

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

La mayoría de las personas lo hacen incorrectamente de esta manera:

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

Encontré este chicos Convertir matriz a imagen

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