Ubah bitmap menjadi array byte


233

Menggunakan C #, apakah ada cara yang lebih baik untuk mengkonversi Windows Bitmapke byte[]daripada menyimpan ke file sementara dan membaca hasilnya menggunakan FileStream?

Jawaban:


419

Ada beberapa cara.

ImageConverter

public static byte[] ImageToByte(Image img)
{
    ImageConverter converter = new ImageConverter();
    return (byte[])converter.ConvertTo(img, typeof(byte[]));
}

Yang ini nyaman karena tidak memerlukan banyak kode.

Aliran Memori

public static byte[] ImageToByte2(Image img)
{
    using (var stream = new MemoryStream())
    {
        img.Save(stream, System.Drawing.Imaging.ImageFormat.Png);
        return stream.ToArray();
    }
}

Yang ini setara dengan apa yang Anda lakukan, kecuali file disimpan ke memori, bukan ke disk. Meskipun lebih banyak kode Anda memiliki pilihan ImageFormat dan dapat dengan mudah dimodifikasi antara menyimpan ke memori atau disk.

Sumber: http://www.vcskicks.com/image-to-byte.php


2
Anda juga dapat menggunakan bitmap.Lockbits dan Marshal.Copy untuk salinan cepat sederhana tanpa ada
stream memori

4
Perlu diketahui bahwa ImageConvertermetode ini akan menyimpan gambar sebagai Png, menghasilkan file BESAR.
skolima

8
Anda tidak perlu menutup aliran saat menggunakan 'menggunakan'
LastTribunal

2
Adakah yang bisa memberi saya sedikit informasi lebih lanjut tentang bagaimana array ini disusun? Apakah ini dimulai dengan x = 0 dan siklus setiap y dan kemudian bertambah x? Dan kemudian simpan seperti ini: [0,0,1,1,1,1,0,0,1,1]?
Raymond Timmermans

1
ImageConverterbukan standar .net yang mungkin Anda gunakanMemoryStream
Alexandre

95

Sebuah MemoryStream dapat membantu untuk ini. Anda bisa memasukkannya dalam metode ekstensi:

public static class ImageExtensions
{
    public static byte[] ToByteArray(this Image image, ImageFormat format)
    {
        using(MemoryStream ms = new MemoryStream())
        {
            image.Save(ms, format);
            return ms.ToArray();
        }
    }
}

Anda bisa menggunakannya seperti:

var image = new Bitmap(10, 10);
// Draw your image
byte[] arr = image.ToByteArray(ImageFormat.Bmp);

Saya sebagian tidak setuju dengan jawaban prestomanifto sehubungan dengan ImageConverter. Jangan gunakan ImageConverter. Tidak ada yang salah secara teknis dengan itu, tetapi hanya fakta bahwa ia menggunakan tinju / unboxing dari objek memberitahu saya itu kode dari tempat-tempat gelap tua dari kerangka NET. Dan itu tidak ideal untuk digunakan dengan pemrosesan gambar (itu terlalu banyak untuk mengkonversi ke byte [] setidaknya), terutama ketika Anda mempertimbangkan yang berikut ini.

Saya melihat ImageConverterkode yang digunakan oleh .Net framework, dan secara internal ia menggunakan kode yang hampir identik dengan yang saya berikan di atas. Itu menciptakan yang baru MemoryStream, menyimpan Bitmapdalam format apa pun itu ketika Anda memberikannya, dan mengembalikan array. Lewati overhead tambahan untuk membuat ImageConverterkelas dengan menggunakanMemoryStream


Menyenangkan. Itu akan berhasil! Saya kira Anda akan ingin membuang MemoryStream, meskipun - peduli untuk memperbarui?
Jeremy McGee

Saya telah memperbarui jawaban saya dengan beberapa diskusi tentang mengapa tidak menggunakan ImageConverter, seperti jawaban pilihan Anda menyarankan, serta penambahan pembuangan.
Christopher Currens

Penggunaan metode ekstensi yang bagus, saya suka!
Dude Pascalou

3
+1 untuk melihat ke ImageConverter dan melaporkan hasil penelitian Anda. Tapi saya tidak berpikir apa yang Anda temukan menjamin pernyataan "Jangan gunakan ImageConverter." Ini pasti memberikan layanan yang bermanfaat dengan cara lain, dari array byte ke Gambar, misalnya mengatur resolusi gambar (dpi). Dan "overhead tambahan untuk menciptakan kelas ImageConverter" mungkin diabaikan, dan hanya perlu dilakukan sekali terlepas dari berapa kali Anda menggunakannya.
RenniePet

1
Saya menemukan ImageConverter juga membantu karena dapat menentukan jenis gambar secara otomatis - misalnya jika Anda memiliki array byte gambar, tetapi tidak tahu formatnya - Anda dapat mencoba membaca header dan mendapatkan petunjuk dari sana, tetapi, baik, ... menggunakan (Gambar img = (Gambar) myImgConverter.ConvertFrom (byteImage)) dan kemudian memeriksa img.PixelFormat dll. lebih mudah .. - tentu saja tergantung pada apa yang ingin Anda lakukan
hello_earth

46

Anda juga bisa Marshal. Salin data bitmap. Tidak ada aliran memori perantara dll. Dan salinan memori cepat. Ini harus bekerja pada bitmap 24-bit dan 32-bit.

public static byte[] BitmapToByteArray(Bitmap bitmap)
{

    BitmapData bmpdata = null;

    try
    {
        bmpdata = bitmap.LockBits(new Rectangle(0, 0, bitmap.Width, bitmap.Height), ImageLockMode.ReadOnly, bitmap.PixelFormat);
        int numbytes = bmpdata.Stride * bitmap.Height;
        byte[] bytedata = new byte[numbytes];
        IntPtr ptr = bmpdata.Scan0;

        Marshal.Copy(ptr, bytedata, 0, numbytes);

        return bytedata;
    }
    finally
    {
        if (bmpdata != null)
            bitmap.UnlockBits(bmpdata);
    }

}

.


1
Hai, saya menggunakan metode ini, tetapi saya tidak dapat mengubah array byte ini kembali ke gambar lagi. Bitmap bitmap1 = Bitmap baru (MemoryStream (array) baru)); itu melempar pengecualian parameter yang tidak valid. Apakah ada kesalahan?
Howard

1
Hai, bagian komentar terlalu kecil bagi saya untuk mengirim kode bersih penuh. Cara paling sederhana adalah menyematkan array: GCHandle handle = GCHandle.Alloc (bufferarray, GCHandleType.Pinned); dapatkan pointer ke array IntPtr iptr = Marshal.UnsafeAddrOfPinnedArrayElement (bufferarray, 0); kemudian buat bitmap baru menggunakan IntPtr: bitmap = Bitmap baru (lebar, tinggi, (lebar * 4), PixelFormat.Format32bppArgb, iptr); tetapi Anda harus menggunakan parameter pembuatan bitmap yang sesuai untuk format bitmap Anda. Pastikan untuk membersihkan: iptr = IntPtr.Zero; handle.Free ();
Deegee

3
Apa bugnya? Banyak programmer termasuk saya menggunakan gaya kode ini dan berfungsi dengan baik.
deegee

4
@ mini-me - Saya sarankan mencari apa langkah bitmap versus lebar bitmap. Ini bukan bug dalam kode saya, ini adalah bagaimana Windows menangani bitmap. Stride dapat menyertakan data tambahan di akhir setiap baris (lebar) agar masing-masing ujung baris dan mulai pada batas 32-bit untuk penyelarasan dan kinerja memori.
Deegee


16

Simpan Gambar ke MemoryStream dan kemudian ambil array byte.

http://msdn.microsoft.com/en-us/library/ms142148.aspx

  Byte[] data;

  using (var memoryStream = new MemoryStream())
  {
    image.Save(memoryStream, ImageFormat.Bmp);

    data = memoryStream.ToArray();
  }

Tidak ada metode Simpan di Gambar.
Prescott Chartier

@PrescottChartier Contoh di atas mengasumsikan Anda bekerja dari jenis yang berasal dari System.Drawing.Image (lihat: docs.microsoft.com/en-us/dotnet/api/… )
Chris Baxter

Ya dan saya mengerti System.Drawing.Image does not exist. Jadi .. tidak, tidak bekerja :(
Prescott Chartier

Anda dapat melihat apa yang saya coba lakukan di sini: stackoverflow.com/questions/55084620/…
Prescott Chartier

10

Gunakan MemoryStreambukan FileStream, a , seperti ini:

MemoryStream ms = new MemoryStream();
bmp.Save (ms, ImageFormat.Jpeg);
byte[] bmpBytes = ms.ToArray();

Anda mungkin ingin ToArray, bukan GetBuffer.
vcsjones

GetBuffer mengembalikan array byte yang tidak ditandatangani (byte array)
Jeff Reddy

4
Itu bisa memiliki data pengisi yang bukan bagian dari gambar. Dari dokumen: Note that the buffer contains allocated bytes which might be unused. For example, if the string "test" is written into the MemoryStream object, the length of the buffer returned from GetBuffer is 256, not 4, with 252 bytes unused. To obtain only the data in the buffer, use the ToArray method.Jadi sekarang array byte dari GetBufferakan mengembalikan gambar plus byte yang tidak digunakan, yang mungkin akan menghasilkan gambar yang rusak.
vcsjones

1
Senang mendengarnya. Terima kasih atas vcs komentar!
Jeff Reddy

Pendekatan ini menyimpan gambar sebagai jpeg dengan pengaturan kompresi default, yang akan memperkenalkan artefak kompresi yang mungkin secara nyata menurunkan gambar Anda.
Richard Ev

8

Coba yang berikut ini:

MemoryStream stream = new MemoryStream();
Bitmap bitmap = new Bitmap();
bitmap.Save(stream, ImageFormat.Jpeg);

byte[] byteArray = stream.GetBuffer();

Pastikan Anda menggunakan:

System.Drawing & using System.Drawing.Imaging;

1
Pendekatan ini menyimpan gambar sebagai jpeg dengan pengaturan kompresi default, yang akan memperkenalkan artefak kompresi yang mungkin secara nyata menurunkan gambar Anda.
Richard Ev

Sekali lagi, tidak ada metode Simpan di bitmap.
Prescott Chartier

7

Saya yakin Anda bisa melakukannya:

ImageConverter converter = new ImageConverter();
var bytes = (byte[])converter.ConvertTo(img, typeof(byte[]));

6
MemoryStream ms = new MemoryStream();
yourBitmap.Save(ms, ImageFormat.Bmp);
byte[] bitmapData = ms.ToArray();

5

Lebih sederhana:

return (byte[])System.ComponentModel.TypeDescriptor.GetConverter(pImagen).ConvertTo(pImagen, typeof(byte[]))

-4

Sangat sederhana gunakan ini hanya dalam satu baris:

byte[] imgdata = File.ReadAllBytes(@"C:\download.png");

op mengatakan dia tidak tertarik dengan opsi ini
Mauro Sampietro
Dengan menggunakan situs kami, Anda mengakui telah membaca dan memahami Kebijakan Cookie dan Kebijakan Privasi kami.
Licensed under cc by-sa 3.0 with attribution required.