Como converter imagem em matriz de bytes

125

Alguém pode sugerir como posso converter uma imagem em uma matriz de bytes e vice-versa?

Estou desenvolvendo um aplicativo WPF e usando um leitor de fluxo.

Shashank
fonte

Respostas:

174

Código de amostra para transformar uma imagem em uma 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 e Byte Array to Image Converter Class

Pranay Rana
fonte
12
em vez de System.Drawing.Imaging.ImageFormat.Gif, você pode usarimageIn.RawFormat
S.Serpooshan
1
Isso não parece ser repetível, ou pelo menos depois de algumas vezes de conversão, erros GDI + estranhos começam a ocorrer. A ImageConvertersolução encontrada abaixo parece evitar esses erros.
Dave Cousineau de
Pode ser melhor usar png, agora.
Nyerguds
Em uma nota lateral: Isso pode conter metadados adicionais que você não deseja ter ;-) Para se livrar dos metadados, você pode querer criar um novo Bitmap e passar a Imagem para ele (new Bitmap(imageIn)).Save(ms, imageIn.RawFormat);.
Markus Safar
56

Para converter um objeto de imagem para byte[] você pode fazer o seguinte:

public static byte[] converterDemo(Image x)
{
    ImageConverter _imageConverter = new ImageConverter();
    byte[] xByte = (byte[])_imageConverter.ConvertTo(x, typeof(byte[]));
    return xByte;
}
AR5HAM
fonte
4
Resposta perfeita! .... não há necessidade de definir a "extensão do arquivo de imagem", exatamente o que eu estava procurando.
Bravo,
1
Em uma nota lateral: Isso pode conter metadados adicionais que você não deseja ter ;-) Para se livrar dos metadados, você pode querer criar um novo Bitmap e passar a Imagem para ele .ConvertTo(new Bitmap(x), typeof(byte[]));.
Markus Safar
1
Para mim, o Visual Studio não está reconhecendo o tipo ImageConverter. Existe uma instrução de importação necessária para usar isso?
technoman23
32

Outra maneira de obter a matriz de bytes do caminho da imagem é

byte[] imgdata = System.IO.File.ReadAllBytes(HttpContext.Current.Server.MapPath(path));
Neelam
fonte
A pergunta deles está marcada como WPF (portanto, não há razão para pensar que está sendo executado em um servidor e inclui um MapPath) E mostra que eles já têm a imagem (não há razão para lê-la do disco, nem mesmo supor que esteja no disco para começar). Sinto muito, mas sua resposta parece completamente irrelevante para a pergunta
Ronan Thibaudau
19

Aqui está o que estou usando atualmente. Algumas das outras técnicas que tentei não foram ótimas porque alteraram a profundidade de bits dos pixels (24 bits x 32 bits) ou ignoraram a resolução da imagem (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();

Imagem para 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 para imagem:

  /// <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 obter a imagem de um arquivo jpg ou png, você deve ler o arquivo em uma matriz de bytes usando File.ReadAllBytes ():

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

Isso evita problemas relacionados ao Bitmap que deseja que seu fluxo de origem seja mantido aberto e algumas soluções alternativas sugeridas para esse problema que resultam em manter o arquivo de origem bloqueado.

RenniePet
fonte
Durante o teste, eu pegaria o bitmap resultante e o transformaria em uma matriz de bytes usando: ImageConverter _imageConverter = new ImageConverter(); lock(SourceImage) { return (byte[])_imageConverter.ConvertTo(SourceImage, typeof(byte[])); } Onde resultaria intermitentemente em matrizes de 2 tamanhos diferentes. Isso normalmente aconteceria após cerca de 100 iterações, mas quando obtenho o bitmap usando new Bitmap(SourceFileName);e o executo por meio desse código, ele funciona bem.
Dom
@Don: Não tenho boas ideias. É consistente quais imagens não resultam na mesma saída como entrada? Você já tentou examinar a saída quando não era a esperada para ver por que é diferente? Ou talvez isso realmente não importe, e pode-se simplesmente aceitar que "coisas acontecem".
RenniePet
Estava acontecendo de forma consistente. Mas nunca encontrei a causa. Tenho a sensação de que pode ter algo a ver com um limite de bytes de 4K na alocação de memória. Mas isso pode facilmente estar errado. Eu mudei para usar um MemoryStream com um BinaryFormatter e fui capaz de me tornar muito consistente, testado com mais de 250 imagens de teste diferentes de formatos e tamanhos variados, repetidas mais de 1000 vezes para verificação. Obrigado pela resposta.
Dom
17

tente isto:

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;
}
anishMarokey
fonte
imageToByteArray (System.Drawing.Image imageIn) imageIn é o caminho da imagem ou qualquer outra coisa como podemos passar a imagem neste
Shashank
Isso é o que eu faço sempre que preciso converter uma imagem em uma matriz de bytes ou vice-versa.
Alex Essilfie
Você se esqueceu de fechar o fluxo de memória ... a propósito, isto foi copiado diretamente de: link
Qwerty01 01 de
1
@ Qwerty01 Chamar o Dispose não limpará a memória usada com MemoryStreammais rapidez, pelo menos na implementação atual. Na verdade, se você fechá-lo, não será capaz de usar o Imagedepois, você obterá um erro de GDI.
Saeb Amini
14

Você pode usar o File.ReadAllBytes()método para ler qualquer arquivo na matriz de bytes. Para escrever a matriz de bytes no arquivo, basta usar o File.WriteAllBytes()método.

Espero que isto ajude.

Você pode encontrar mais informações e código de amostra aqui .

Shekhar
fonte
Apenas uma observação lateral: isso pode conter metadados adicionais que você não deseja ter ;-)
Markus Safar
1
Talvez. Escrevi esta resposta há 10 anos, era mais novo / novato naquela época.
Shekhar
5

Você deseja apenas os pixels ou a imagem inteira (incluindo cabeçalhos) como uma matriz de bytes?

Para pixels: use o CopyPixelsmétodo em Bitmap. 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); 
Lasse Espeholt
fonte
3

Código:

using System.IO;

byte[] img = File.ReadAllBytes(openFileDialog1.FileName);
Md Shahriar
fonte
1
Só funciona se ele estiver lendo um arquivo (e mesmo assim ele obtém os bytes formatados / compactados, não os brutos, a menos que seja um BMP)
BradleyDotNET
3

Se você não fizer referência a imageBytes para transportar bytes no fluxo, o método não retornará nada. Certifique-se de fazer referência 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] Se você ainda não consegue ver a imagem no navegador, escrevi uma etapa de solução de problemas detalhada

resolvido! -iis-not-serving-css, -images-and-javascript

Ernest www.ernestech.com
fonte
1

Este é o código para converter a imagem de qualquer tipo (por exemplo PNG, JPG, JPEG) em uma 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
    }
Sureya Pragaash
fonte
Apenas uma observação lateral: isso pode conter metadados adicionais que você não deseja ter ;-)
Markus Safar
0

Para converter a imagem em uma matriz de bytes. O código é fornecido abaixo.

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

Para converter a matriz de bytes em imagem. O código é fornecido a seguir. O código é manipulado A Generic error occurred in GDI+em Salvar imagem.

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();
    }
}
Bibin
fonte
-2

Este código recupera as primeiras 100 linhas da tabela no SQLSERVER 2012 e salva uma imagem por linha como um arquivo no 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();
               }

    }

observe: o diretório com o nome NewFolder deve existir em C: \

Reza
fonte
3
Você respondeu a pergunta errada ... Bem, espero ^ _ ^
JiBéDoublevé