Как преобразовать изображение в байтовый массив

126

Может ли кто-нибудь подсказать, как преобразовать изображение в массив байтов и наоборот?

Я разрабатываю приложение WPF и использую средство чтения потоков.

Shashank
источник

Ответы:

175

Пример кода для преобразования изображения в массив байтов

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

C # изображение в байтовый массив и байтовый массив в класс конвертера изображений

Праная Рана
источник
12
вместо System.Drawing.Imaging.ImageFormat.Gif, вы можете использоватьimageIn.RawFormat
С.Серпушан
1
Это не похоже на повторяемость, или, по крайней мере, после пары раз преобразования начинают возникать странные ошибки GDI +. ImageConverterНайденное решение ниже , кажется , чтобы избежать этих ошибок.
Dave
Возможно, сейчас лучше использовать png.
Nyerguds
На стороне записки: Это может содержать дополнительные данные меты вы не хотите иметь ;-) Для того, чтобы избавиться от метаданных вы можете захотеть создать новый Bitmap и передать изображение на него , как (new Bitmap(imageIn)).Save(ms, imageIn.RawFormat);.
Маркус Сафар,
56

Для преобразования объекта Image в byte[]вы можете сделать следующее:

public static byte[] converterDemo(Image x)
{
    ImageConverter _imageConverter = new ImageConverter();
    byte[] xByte = (byte[])_imageConverter.ConvertTo(x, typeof(byte[]));
    return xByte;
}
AR5HAM
источник
4
Идеальный ответ! .... не нужно определять «расширение файла изображения», именно то, что я искал.
Bravo
1
На стороне записки: Это может содержать дополнительные данные меты вы не хотите иметь ;-) Для того, чтобы избавиться от метаданных вы можете захотеть создать новый Bitmap и передать изображение на него , как .ConvertTo(new Bitmap(x), typeof(byte[]));.
Маркус Сафар,
1
Для меня Visual Studio не распознает тип ImageConverter. Для этого нужен оператор импорта?
technoman23,
32

Другой способ получить массив байтов из пути к изображению -

byte[] imgdata = System.IO.File.ReadAllBytes(HttpContext.Current.Server.MapPath(path));
Нилам
источник
Их вопрос помечен как WPF (так что нет причин думать, что он работает на сервере и включает MapPath) И показывает, что у них уже есть изображение (нет причин читать его с диска, даже не предполагать, что оно находится на диске). Извините, но ваш ответ кажется совершенно не относящимся к вопросу
Ронан Тибодау
19

Вот что я сейчас использую. Некоторые из других техник, которые я пробовал, оказались неоптимальными, потому что они меняли битовую глубину пикселей (24 бит против 32 бит) или игнорировали разрешение изображения (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();

Изображение в байтовый массив:

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

Байтовый массив в изображение:

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

Изменить: чтобы получить изображение из файла jpg или png, вы должны прочитать файл в массив байтов с помощью File.ReadAllBytes ():

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

Это позволяет избежать проблем, связанных с тем, что Bitmap хочет, чтобы его исходный поток оставался открытым, и некоторых предлагаемых обходных путей для этой проблемы, которые приводят к тому, что исходный файл остается заблокированным.

RenniePet
источник
Во время тестирования я бы взял полученное растровое изображение и превратил его в массив байтов, используя: ImageConverter _imageConverter = new ImageConverter(); lock(SourceImage) { return (byte[])_imageConverter.ConvertTo(SourceImage, typeof(byte[])); } Где это периодически приводило бы к массивам двух разных размеров. Обычно это происходит примерно после 100 итераций, но когда я получаю растровое изображение, используя, new Bitmap(SourceFileName);а затем пропускаю его через этот код, он работает нормально.
Дон
@Don: У меня действительно нет хороших идей. Последовательно ли, какие изображения не приводят к тому же результату, что и входные? Вы пытались изучить результат, когда он не такой, как ожидалось, чтобы понять, почему он другой? Или, может быть, это не имеет значения, и можно просто принять, что «вещи случаются».
RenniePet
Это происходило постоянно. Но так и не нашел причину. У меня такое чувство, что это могло иметь какое-то отношение к границе 4К байта при распределении памяти. Но это могло легко ошибиться. Я переключился на использование MemoryStream с BinaryFormatter, и я смог стать очень последовательным, протестировав более 250 различных тестовых изображений разных форматов и размеров, зацикленных более 1000 раз для проверки. Спасибо за ваш ответ.
Дон
17

попробуй это:

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
источник
imageToByteArray (System.Drawing.Image imageIn) imageIn - это путь к изображению или что-то еще, как мы можем передать изображение в этом
Shashank
Это то, что я делаю каждый раз, когда мне нужно преобразовать изображение в байтовый массив или обратно.
Alex Essilfie
Вы забыли закрыть поток памяти ... кстати, это скопировано прямо из: ссылка
Qwerty01 01
1
@ Qwerty01 Вызов Dispose не очистит используемую память MemoryStreamбыстрее, по крайней мере, в текущей реализации. Фактически, если вы закроете его, вы не сможете использовать его Imageвпоследствии, вы получите ошибку GDI.
Саеб Амини
14

Вы можете использовать File.ReadAllBytes()метод для чтения любого файла в байтовый массив. Чтобы записать байтовый массив в файл, просто используйте File.WriteAllBytes()метод.

Надеюсь это поможет.

Вы можете найти дополнительную информацию и образец кода здесь .

Шекхар
источник
Небольшое примечание: это может содержать дополнительные метаданные, которые вам не нужны ;-)
Маркус Сафар,
1
Может быть. Я написал этот ответ 10 лет назад, тогда я был посвежее / нуб.
Шекхар
5

Вам нужны только пиксели или все изображение (включая заголовки) в виде байтового массива?

Для пикселей: используйте CopyPixelsметод Bitmap. Что-то вроде:

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

Код:

using System.IO;

byte[] img = File.ReadAllBytes(openFileDialog1.FileName);
Md Shahriar
источник
1
Работает только в том случае, если он читает файл (и даже тогда он получает отформатированные / сжатые байты, а не сырые, если это не BMP)
BradleyDotNET
3

Если вы не ссылаетесь на imageBytes для переноса байтов в потоке, метод ничего не вернет. Убедитесь, что вы ссылаетесь на 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] Если вы все еще не видите изображение в браузере, я написал подробный шаг по устранению неполадок.

решена! -iis-не-сервировка-CSS,-и-образами-JavaScript

Эрнест www.ernestech.com
источник
1

Это Код для преобразования изображения любого типа (например PNG, JPG, JPEG) в байтовый массив.

   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
    }
Сурея Прагааш
источник
Небольшое примечание: это может содержать дополнительные метаданные, которые вам не нужны ;-)
Маркус Сафар,
0

Чтобы преобразовать изображение в байтовый массив, код приведен ниже.

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

Чтобы преобразовать массив байтов в изображение, код приведен ниже. Код является дескриптором A Generic error occurred in GDI+в Image Save.

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

Этот код извлекает первые 100 строк из таблицы в SQLSERVER 2012 и сохраняет изображение для каждой строки как файл на локальном диске.

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

    }

обратите внимание: каталог с именем NewFolder должен существовать в C: \

Реза
источник
3
Вы ответили не на тот вопрос ... Надеюсь, ^ _ ^
JiBéDoublevé