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.