Cómo convertir una imagen a una matriz de bytes


125

¿Alguien puede sugerir cómo puedo convertir una imagen en una matriz de bytes y viceversa?

Estoy desarrollando una aplicación WPF y usando un lector de flujo.

Respuestas:


174

Código de muestra para cambiar una imagen en una matriz de bytes

public byte[] ImageToByteArray(System.Drawing.Image imageIn)
{
   using (var ms = new MemoryStream())
   {
      imageIn.Save(ms,imageIn.RawFormat);
      return  ms.ToArray();
   }
}

C # Image to Byte Array y Byte Array to Image Converter Class


12
en lugar de System.Drawing.Imaging.ImageFormat.Gif, puede usarimageIn.RawFormat
S.Serpooshan

1
Esto no parece ser repetible, o al menos después de un par de veces de conversión, comienzan a ocurrir errores extraños de GDI +. La ImageConvertersolución que se encuentra a continuación parece evitar estos errores.
Dave Cousineau

Podría ser mejor usar png hoy en día.
Nyerguds

En una nota al margen: esto puede contener metadatos adicionales que no desea tener ;-) Para deshacerse de los metadatos, es posible que desee crear un nuevo mapa de bits y pasarle la imagen como (new Bitmap(imageIn)).Save(ms, imageIn.RawFormat);.
Markus Safar

56

Para convertir un objeto de imagen en byte[]puede hacer lo siguiente:

public static byte[] converterDemo(Image x)
{
    ImageConverter _imageConverter = new ImageConverter();
    byte[] xByte = (byte[])_imageConverter.ConvertTo(x, typeof(byte[]));
    return xByte;
}

4
¡Respuesta perfecta! .... No es necesario definir la "extensión del archivo de imagen", exactamente lo que estaba buscando.
Bravo

1
En una nota al margen: esto puede contener metadatos adicionales que no desea tener ;-) Para deshacerse de los metadatos, es posible que desee crear un nuevo mapa de bits y pasarle la imagen como .ConvertTo(new Bitmap(x), typeof(byte[]));.
Markus Safar

1
Para mí, Visual Studio no reconoce el tipo ImageConverter. ¿Se necesita una declaración de importación para usar esto?
technoman23

32

Otra forma de obtener la matriz de bytes de la ruta de la imagen es

byte[] imgdata = System.IO.File.ReadAllBytes(HttpContext.Current.Server.MapPath(path));

Su pregunta está etiquetada como WPF (por lo que no hay razón para pensar que se está ejecutando en un servidor e incluye un MapPath) Y muestra que ya tienen la imagen (no hay razón para leerla desde el disco, ni siquiera asumir que está en el disco para empezar). Lo siento, pero su respuesta parece completamente irrelevante para la pregunta
Ronan Thibaudau

19

Esto es lo que estoy usando actualmente. Algunas de las otras técnicas que he probado no han sido óptimas porque cambiaron la profundidad de bits de los píxeles (24 bits frente a 32 bits) o ignoraron la resolución de la imagen (dpi).

  // ImageConverter object used to convert byte arrays containing JPEG or PNG file images into 
  //  Bitmap objects. This is static and only gets instantiated once.
  private static readonly ImageConverter _imageConverter = new ImageConverter();

Imagen a matriz de bytes:

  /// <summary>
  /// Method to "convert" an Image object into a byte array, formatted in PNG file format, which 
  /// provides lossless compression. This can be used together with the GetImageFromByteArray() 
  /// method to provide a kind of serialization / deserialization. 
  /// </summary>
  /// <param name="theImage">Image object, must be convertable to PNG format</param>
  /// <returns>byte array image of a PNG file containing the image</returns>
  public static byte[] CopyImageToByteArray(Image theImage)
  {
     using (MemoryStream memoryStream = new MemoryStream())
     {
        theImage.Save(memoryStream, ImageFormat.Png);
        return memoryStream.ToArray();
     }
  }

Matriz de bytes a imagen:

  /// <summary>
  /// Method that uses the ImageConverter object in .Net Framework to convert a byte array, 
  /// presumably containing a JPEG or PNG file image, into a Bitmap object, which can also be 
  /// used as an Image object.
  /// </summary>
  /// <param name="byteArray">byte array containing JPEG or PNG file image or similar</param>
  /// <returns>Bitmap object if it works, else exception is thrown</returns>
  public static Bitmap GetImageFromByteArray(byte[] byteArray)
  {
     Bitmap bm = (Bitmap)_imageConverter.ConvertFrom(byteArray);

     if (bm != null && (bm.HorizontalResolution != (int)bm.HorizontalResolution ||
                        bm.VerticalResolution != (int)bm.VerticalResolution))
     {
        // Correct a strange glitch that has been observed in the test program when converting 
        //  from a PNG file image created by CopyImageToByteArray() - the dpi value "drifts" 
        //  slightly away from the nominal integer value
        bm.SetResolution((int)(bm.HorizontalResolution + 0.5f), 
                         (int)(bm.VerticalResolution + 0.5f));
     }

     return bm;
  }

Editar: para obtener la imagen de un archivo jpg o png, debe leer el archivo en una matriz de bytes usando File.ReadAllBytes ():

 Bitmap newBitmap = GetImageFromByteArray(File.ReadAllBytes(fileName));

Esto evita problemas relacionados con Bitmap que desea que su flujo de origen se mantenga abierto, y algunas soluciones alternativas sugeridas para ese problema que dan como resultado que el archivo de origen se mantenga bloqueado.


Durante la prueba de esto, tomaría el mapa de bits resultante y lo volvería a convertir en una matriz de bytes usando: ImageConverter _imageConverter = new ImageConverter(); lock(SourceImage) { return (byte[])_imageConverter.ConvertTo(SourceImage, typeof(byte[])); } Donde resultaría intermitentemente en matrices de 2 tamaños diferentes. Esto normalmente sucedería después de aproximadamente 100 iteraciones, pero cuando obtengo el mapa de bits new Bitmap(SourceFileName);y luego lo ejecuto a través de ese código, funciona bien.
Don

@Don: Realmente no tengo buenas ideas. ¿Es coherente qué imágenes no dan el mismo resultado que la entrada? ¿Ha intentado examinar el resultado cuando no es el esperado para ver por qué es diferente? O tal vez no importa realmente, y uno puede simplemente aceptar que "las cosas pasan".
RenniePet

Estaba sucediendo constantemente. Sin embargo, nunca encontré la causa. Tengo la sensación de que podría haber tenido algo que ver con un límite de bytes de 4K en la asignación de memoria. Pero eso fácilmente podría estar mal. Cambié a usar MemoryStream con BinaryFormatter y pude volverme muy consistente al probar con más de 250 imágenes de prueba diferentes de diferentes formatos y tamaños, en bucle más de 1000 veces para verificación. Gracias por la respuesta.
Don

17

prueba esto:

public byte[] imageToByteArray(System.Drawing.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;
}

imageToByteArray (System.Drawing.Image imageIn) imageIn es la ruta de la imagen o cualquier otra cosa, cómo podemos pasar la imagen en esto
Shashank

Esto es lo que hago cada vez que necesito convertir una imagen en una matriz de bytes o viceversa.
Alex Essilfie

Olvidó cerrar el flujo de memoria ... por cierto, esto se copia directamente de: enlace
Qwerty01

1
@ Qwerty01 Llamar a Dispose no limpiará la memoria utilizada por MemoryStreammás rápido, al menos en la implementación actual. De hecho, si lo cierra, no podrá usar el Imagedespués, obtendrá un error GDI.
Saeb Amini

14

Puede usar el File.ReadAllBytes()método para leer cualquier archivo en una matriz de bytes. Para escribir una matriz de bytes en un archivo, simplemente use el File.WriteAllBytes()método.

Espero que esto ayude.

Puede encontrar más información y código de muestra aquí .


Solo una nota al margen: esto puede contener metadatos adicionales que no desea tener ;-)
Markus Safar

1
Tal vez. Escribí esta respuesta hace 10 años, era más fresco / novato en ese entonces.
Shekhar

5

¿Solo desea los píxeles o la imagen completa (incluidos los encabezados) como una matriz de bytes?

Para píxeles: utilice el CopyPixelsmétodo en mapa de bits. Algo como:

var bitmap = new BitmapImage(uri);

//Pixel array
byte[] pixels = new byte[width * height * 4]; //account for stride if necessary and whether the image is 32 bit, 16 bit etc.

bitmap.CopyPixels(..size, pixels, fullStride, 0); 

3

Código:

using System.IO;

byte[] img = File.ReadAllBytes(openFileDialog1.FileName);

1
Solo funciona si está leyendo un archivo (e incluso entonces obtiene los bytes formateados / comprimidos, no los sin formato a menos que sea un BMP)
BradleyDotNET

3

Si no hace referencia a imageBytes para transportar bytes en la secuencia, el método no devolverá nada. Asegúrese de hacer referencia a imageBytes = m.ToArray ();

    public static byte[] SerializeImage() {
        MemoryStream m;
        string PicPath = pathToImage";

        byte[] imageBytes;
        using (Image image = Image.FromFile(PicPath)) {

            using ( m = new MemoryStream()) {

                image.Save(m, image.RawFormat);
                imageBytes = new byte[m.Length];
               //Very Important    
               imageBytes = m.ToArray();

            }//end using
        }//end using

        return imageBytes;
    }//SerializeImage

[NB] Si aún no ve la imagen en el navegador, escribí un paso de solución de problemas detallado

resuelto! -iis-not-serve-css, -images-and-javascript


1

Este es un código para convertir la imagen de cualquier tipo (por ejemplo, PNG, JPG, JPEG) a una matriz de bytes

   public static byte[] imageConversion(string imageName){            


        //Initialize a file stream to read the image file
        FileStream fs = new FileStream(imageName, FileMode.Open, FileAccess.Read);

        //Initialize a byte array with size of stream
        byte[] imgByteArr = new byte[fs.Length];

        //Read data from the file stream and put into the byte array
        fs.Read(imgByteArr, 0, Convert.ToInt32(fs.Length));

        //Close a file stream
        fs.Close();

        return imageByteArr
    }

Solo una nota al margen: esto puede contener metadatos adicionales que no desea tener ;-)
Markus Safar

0

Para convertir la imagen en una matriz de bytes, el código se da a continuación.

public byte[] ImageToByteArray(System.Drawing.Image images)
{
   using (var _memorystream = new MemoryStream())
   {
      images.Save(_memorystream ,images.RawFormat);
      return  _memorystream .ToArray();
   }
}

Para convertir la matriz de bytes a imagen. El código se proporciona a continuación. El código se maneja A Generic error occurred in GDI+en Guardar imagen.

public void SaveImage(string base64String, string filepath)
{
    // image convert to base64string is base64String 
    //File path is which path to save the image.
    var bytess = Convert.FromBase64String(base64String);
    using (var imageFile = new FileStream(filepath, FileMode.Create))
    {
        imageFile.Write(bytess, 0, bytess.Length);
        imageFile.Flush();
    }
}

-2

Este código recupera las primeras 100 filas de la tabla en SQLSERVER 2012 y guarda una imagen por fila como un archivo en el disco local

 public void SavePicture()
    {
        SqlConnection con = new SqlConnection("Data Source=localhost;Integrated security=true;database=databasename");
        SqlDataAdapter da = new SqlDataAdapter("select top 100 [Name] ,[Picture] From tablename", con);
        SqlCommandBuilder MyCB = new SqlCommandBuilder(da);
        DataSet ds = new DataSet("tablename");
        byte[] MyData = new byte[0];
        da.Fill(ds, "tablename");
        DataTable table = ds.Tables["tablename"];
           for (int i = 0; i < table.Rows.Count;i++ )               
               {
                DataRow myRow;
                myRow = ds.Tables["tablename"].Rows[i];
                MyData = (byte[])myRow["Picture"];
                int ArraySize = new int();
                ArraySize = MyData.GetUpperBound(0);
                FileStream fs = new FileStream(@"C:\NewFolder\" + myRow["Name"].ToString() + ".jpg", FileMode.OpenOrCreate, FileAccess.Write);
                fs.Write(MyData, 0, ArraySize);
                fs.Close();
               }

    }

tenga en cuenta: el directorio con el nombre NewFolder debe existir en C: \


3
Respondiste la pregunta incorrecta ... Bueno, espero ^ _ ^
JiBéDoublevé
Al usar nuestro sitio, usted reconoce que ha leído y comprende nuestra Política de Cookies y Política de Privacidad.
Licensed under cc by-sa 3.0 with attribution required.