Jak przekonwertować obraz na tablicę bajtów


125

Czy ktoś może zasugerować, jak mogę przekonwertować obraz na tablicę bajtów i odwrotnie?

Tworzę aplikację WPF i używam czytnika strumieni.

Odpowiedzi:


174

Przykładowy kod zmieniający obraz w tablicę bajtów

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

C # obraz na tablicę bajtów i tablicę bajtów na klasę konwertera obrazów


12
zamiast tego System.Drawing.Imaging.ImageFormat.Gifmożesz użyćimageIn.RawFormat
— S.Serpooshan

1
Wydaje się, że nie jest to powtarzalne lub przynajmniej po kilkukrotnej konwersji zaczynają się pojawiać dziwne błędy GDI +. Poniższe ImageConverterrozwiązanie wydaje się unikać tych błędów.
— Dave Cousineau

W dzisiejszych czasach lepiej byłoby użyć png.
— Nyerguds

Na marginesie: To może zawierać dodatkowe dane meta nie chcesz mieć ;-) Aby pozbyć metadanych może chcesz stworzyć nową bitmapę i przekazać obraz do niego podobny (new Bitmap(imageIn)).Save(ms, imageIn.RawFormat);.
— Markus Safar

56

Aby przekonwertować obiekt obrazu na byte[], możesz wykonać następujące czynności:

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

4
Doskonała odpowiedź! .... nie ma potrzeby definiowania „rozszerzenia pliku obrazu”, dokładnie tego, czego szukałem.
— Bravo,

1
Na marginesie: To może zawierać dodatkowe dane meta nie chcesz mieć ;-) Aby pozbyć metadanych może chcesz stworzyć nową bitmapę i przekazać obraz do niego podobny .ConvertTo(new Bitmap(x), typeof(byte[]));.
— Markus Safar

1
Dla mnie program Visual Studio nie rozpoznaje typu ImageConverter. Czy do tego jest potrzebna instrukcja importu?
— technoman 23

32

Innym sposobem na pobranie tablicy Byte ze ścieżki obrazu jest

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

Ich pytanie jest oznaczone jako WPF (więc nie ma powodu, by sądzić, że działa na serwerze i zawiera MapPath) ORAZ pokazuje, że mają już obraz (nie ma powodu, aby czytać go z dysku, nawet nie zakładać, że jest na dysku). Przykro mi, ale twoja odpowiedź wydaje się zupełnie nieistotna dla pytania
— Ronan Thibaudau

19

Oto, czego obecnie używam. Niektóre z innych technik, które wypróbowałem, były nieoptymalne, ponieważ zmieniły głębię bitową pikseli (24-bitowa vs 32-bitowa) lub zignorowały rozdzielczość obrazu (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();

Obraz do tablicy bajtów:

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

Tablica bajtów do obrazu:

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

Edycja: Aby pobrać obraz z pliku jpg lub png, należy wczytać plik do tablicy bajtów za pomocą funkcji File.ReadAllBytes ():

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

Pozwala to uniknąć problemów związanych z tym, że Bitmap chce, aby jej strumień źródłowy był otwarty, i niektóre sugerowane obejścia tego problemu, które powodują, że plik źródłowy jest zablokowany.


Podczas testowania tego wziąłbym wynikową bitmapę i przekształciłbym ją z powrotem w tablicę bajtów, używając: ImageConverter _imageConverter = new ImageConverter(); lock(SourceImage) { return (byte[])_imageConverter.ConvertTo(SourceImage, typeof(byte[])); } Gdzie sporadycznie powodowałoby to tablice o 2 różnych rozmiarach. Zwykle zdarza się to po około 100 iteracjach, ale kiedy uzyskam bitmapę za pomocą, new Bitmap(SourceFileName);a następnie przepuszczę ją przez ten kod, działa dobrze.
— Don

@Don: Naprawdę nie mam żadnych dobrych pomysłów. Czy spójne jest, które obrazy nie dają takiego samego wyniku jak dane wejściowe? Czy próbowałeś zbadać wynik, gdy nie jest zgodny z oczekiwaniami, aby zobaczyć, dlaczego jest inny? A może to nie ma znaczenia i można po prostu zaakceptować, że „rzeczy się zdarzają”.
— RenniePet

To się działo konsekwentnie. Jednak nigdy nie znalazłem przyczyny. Wydaje mi się, że mogło to mieć coś wspólnego z granicą 4 KB w alokacji pamięci. Ale to może być błędne. Przerzuciłem się na używanie MemoryStream z BinaryFormatter i byłem w stanie uzyskać dużą spójność w testach z ponad 250 różnymi obrazami testowymi o różnych formatach i rozmiarach, zapętlonych ponad 1000 razy w celu weryfikacji. Dziękuję za odpowiedź.
— Don

17

Spróbuj tego:

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 to ścieżka obrazu lub cokolwiek innego, w jaki sposób możemy przekazać obraz w tym
— Shashank

To jest to, co robię za każdym razem, gdy potrzebuję przekonwertować obraz na tablicę bajtów lub z powrotem.
— Alex Essilfie

Zapomniałeś zamknąć
— strumień wspomnień

1
@ Qwerty01 Wywołanie Dispose nie wyczyści pamięci używanej przez MemoryStreamszybsze, przynajmniej w bieżącej implementacji. W rzeczywistości, jeśli go zamkniesz, nie będziesz mógł użyć Imagepóźniej, otrzymasz błąd GDI.
— Saeb Amini

14

Możesz użyć File.ReadAllBytes()metody, aby wczytać dowolny plik do tablicy bajtów. Aby zapisać tablicę bajtów do pliku, użyj File.WriteAllBytes()metody method.

Mam nadzieję że to pomoże.

Więcej informacji i przykładowy kod znajdziesz tutaj .


Na marginesie: może zawierać dodatkowe metadane, których nie chcesz mieć ;-)
— Markus Safar

1
Może. Napisałem tę odpowiedź 10 lat temu, byłem wtedy świeższy / noob.
— Shekhar

5

Czy chcesz, aby piksele lub cały obraz (łącznie z nagłówkami) był tablicą bajtów?

W przypadku pikseli: użyj CopyPixelsmetody na Bitmap. Coś jak:

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

Kod:

using System.IO;

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

1
Działa tylko wtedy, gdy czyta plik (i nawet wtedy pobiera sformatowane / skompresowane bajty, a nie surowe, chyba że jest to BMP)
— BradleyDotNET

3

Jeśli nie odniesiesz się do imageBytes do przenoszenia bajtów w strumieniu, metoda nie zwróci niczego. Upewnij się, że odwołujesz się do 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] Jeśli nadal nie widzisz obrazu w przeglądarce, napisałem szczegółowy krok rozwiązywania problemów

rozwiązane! -iis-not-Serving-css, -images-and-javascript


1

To jest kod do konwersji obrazu dowolnego typu (na przykład PNG, JPG, JPEG) do tablicy bajtów

   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
    }

Na marginesie: może zawierać dodatkowe metadane, których nie chcesz mieć ;-)
— Markus Safar

0

Aby przekonwertować obraz na tablicę bajtów, kod jest podany poniżej.

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

Aby przekonwertować tablicę Byte na Image. Kod jest podany poniżej. Kod jest obsługiwany A Generic error occurred in GDI+w 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

Ten kod pobiera pierwsze 100 wierszy z tabeli w SQLSERVER 2012 i zapisuje obraz w każdym wierszu jako plik na dysku lokalnym

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

    }

uwaga: katalog z nazwą NewFolder powinien istnieć w C: \


3
Odpowiedziałeś na złe pytanie ... Cóż, mam nadzieję ^ _ ^
— JiBéDoublevé
Korzystając z naszej strony potwierdzasz, że przeczytałeś(-aś) i rozumiesz nasze zasady używania plików cookie i zasady ochrony prywatności.
Licensed under cc by-sa 3.0 with attribution required.