Bir bitmap'i bayt dizisine dönüştürme


233

C # kullanarak, bir Windows'u dönüştürmek için daha iyi bir yol yoktur Bitmapbir karşı byte[]geçici bir dosyaya kaydetme ve bir kullanarak sonuç okumaktan daha FileStream?

Yanıtlar:


418

Birkaç yol var.

ImageConverter

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

Bu, çok fazla kod gerektirmediği için uygundur.

Bellek Akışı

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

Dosya diske değil belleğe kaydedilmiş olması dışında, yaptığınızla eşdeğerdir. Daha fazla kod olmasına rağmen ImageFormat seçeneğiniz vardır ve belleğe veya diske kaydetme arasında kolayca değiştirilebilir.

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


2
Ayrıca hızlı vb herhangi bir ara memorystreams olmadan kopyalamayı bir basit için bitmap.Lockbits ve Marshal.Copy kullanabilirsiniz
DeeGee

4
Lütfen ImageConverteryöntemin resmi Png olarak kaydedeceğini ve BÜYÜK dosyalar elde edeceğini unutmayın.
skolima

8
'kullanarak' kullanırken akışı kapatmanız gerekmez
LastTribunal

2
Kimse bana bu dizinin nasıl yapılandırıldığı hakkında biraz daha bilgi verebilir mi? X = 0 ile başlar ve her y boyunca döngü yapar ve sonra x değerini artırır? Sonra şu şekilde saklayın: [0,0,1,1,1,1,0,0,1,1]?
Raymond Timmermans

1
ImageConverterKullanabileceğiniz .net standardı değilMemoryStream
Alexandre

95

Bir MemoryStream bunun için yardımcı olabilir. Bir uzantı yöntemine koyabilirsiniz:

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

Sadece şöyle kullanabilirsiniz:

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

Prestomanifto'nun ImageConverter ile ilgili cevabına kısmen katılmıyorum. ImageConverter kullanmayın. Teknik olarak yanlış bir şey yok, ancak nesneden boks / kutudan çıkarma kullanması bana .NET çerçevesinin eski karanlık yerlerinden kod olduğunu ve görüntü işleme ile kullanmak için ideal olmadığını söylüyor (bir bayta dönüştürmek için aşırıya kaçıyor) [] en azından), özellikle aşağıdakileri göz önünde bulundurduğunuzda.

ImageConverter.Net çerçevesi tarafından kullanılan koda bir göz attım ve dahili olarak neredeyse yukarıda sağladığımla aynı kodu kullanıyor. Yeni bir dosya oluşturur MemoryStream, Bitmapbunu sağladığınız formatta kaydeder ve diziyi döndürür. ImageConverterKullanarak sınıf oluşturmanın ek yükünü atlaMemoryStream


Güzel. Yapacak! MemoryStream'i atmak isteyeceğinize inanıyorum - güncellemek ister misiniz?
Jeremy McGee

Cevabınızı, seçtiğiniz cevabın önerdiği gibi imha eklenmesinin yanı sıra neden ImageConverter kullanmamanız gerektiğiyle ilgili bazı tartışmalarla güncelledim.
Christopher Currens

Bir uzatma yönteminin güzel kullanımı, beğendim!
Dude Pascalou

3
ImageConverter'a bakmak ve araştırmanızın sonuçlarını raporlamak için +1. Ama keşfettiğiniz şeyin "ImageConverter kullanma" ifadesini gerektirdiğini düşünmüyorum. Kesinlikle bayt dizisinden Resim'e, örneğin görüntü çözünürlüğünü (dpi) ayarlamak için, diğer tarafa giden yararlı hizmetler sağlar. Ve "ImageConverter sınıfı yaratmanın ekstra yükü" muhtemelen önemsizdir ve kaç kez kullandığınızdan bağımsız olarak yalnızca bir kez yapılması gerekir.
RenniePet

1
ImageConverter'ı görüntünün türünü otomatik olarak belirleyebilmesi için de yararlı buldum - örneğin görüntünün bir bayt dizisine sahipseniz, ancak biçimi bilmiyorsanız - üstbilgileri okumayı ve oradan ipuçları almayı deneyebilirsiniz, ancak, kuyu ... kullanarak (Görüntü img = (Görüntü) myImgConverter.ConvertFrom (byteImage)) ve daha sonra kontrol img.PixelFormat vs .. sadece daha kolaydır - Tabii ki ne yapmak istediğinize bağlı olarak
hello_earth

45

Ayrıca sadece Marshal. Bitmap verilerini kopyalayabilirsiniz. Ara bellek akışı vb. Ve hızlı bellek kopyası yok. Bu, hem 24 bit hem de 32 bit bitmap'lerde çalışmalıdır.

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
Merhaba, bu yöntemi kullandım, ancak bu bayt dizisini tekrar bir görüntüye dönüştüremiyorum. Bitmap bitmap1 = yeni Bitmap (yeni MemoryStream (dizi)); geçersiz parametreler istisnası atar. Herhangi bir hata var mı?
Howard

1
Merhaba, yorum bölümü tam temiz kod göndermem için çok küçük. En basit yol diziyi sabitlemektir: GCHandle handle = GCHandle.Alloc (bufferarray, GCHandleType.Pinned); işaretçiyi diziye getirin IntPtr iptr = Marshal.UnsafeAddrOfPinnedArrayElement (bufferarray, 0); daha sonra IntPtr kullanarak yeni bir bitmap oluşturun: bitmap = new Bitmap (width, height, (width * 4), PixelFormat.Format32bppArgb, iptr); ancak bitmap biçiminiz için uygun bitmap oluşturma parametrelerini kullanmanız gerekir. Temizlediğinizden emin olun: iptr = IntPtr.Zero; handle.Free ();
Deegee

3
Hata nedir? Ben de dahil olmak üzere birçok programcı bu kod stilini kullanıyor ve iyi çalışıyor.
Deegee

4
@ mini-me - Bitmap genişliğine karşı ne bitmap adımının bakılmasını öneririm. Bu benim kodumda bir hata değil, Windows bitmap'leri bu şekilde işler. Adım, her bir satırın sonlanması ve bellek hizalaması ve performansı için 32 bitlik bir sınırdan başlaması için her satırın sonunda (genişlik) fazladan veri içerebilir.
Deegee


16

Görüntüyü bir MemoryStream'e kaydedin ve bayt dizisini alın.

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

  Byte[] data;

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

    data = memoryStream.ToArray();
  }

Görüntüde Kaydet yöntemi yoktur.
Prescott Chartier

Eğer elde edilen bir tür çalışan varsayarak yukarıdaki örnekte @PrescottChartier System.Drawing.Image (bakınız: docs.microsoft.com/en-us/dotnet/api/... )
Chris Baxter

Evet ve anlarım System.Drawing.Image does not exist. Yani .. hayır, çalışmıyor :(
Prescott Chartier

Burada ne yapmaya çalıştığımı görebilirsiniz: stackoverflow.com/questions/55084620/…
Prescott Chartier

10

MemoryStreamBunun yerine a yerine kullanın FileStream:

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

Muhtemelen istiyorsun ToArray, değil GetBuffer.
vcsjones

GetBuffer, imzalanmamış bayt dizisini döndürür (bayt dizisi)
Jeff Reddy

4
Görüntünün bir parçası olmayan dolgu verileri olabilir. Dokümanlar'dan: 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.Şimdi gelen bayt dizisi GetBuffergörüntüyü artı kullanılmayan baytları döndürecek ve bu da muhtemelen bozuk bir görüntüye neden olacaktır.
vcsjones

1
Bunu bildiğim iyi oldu. Yorum için teşekkürler vcs!
Jeff Reddy

Bu yaklaşım, görüntüyü, görüntünüzü görünür bir şekilde bozabilecek sıkıştırma artefaktları tanıtacak olan varsayılan sıkıştırma ayarlarına sahip bir jpeg olarak kaydeder.
Richard Ev

8

Takip etmeyi dene:

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

byte[] byteArray = stream.GetBuffer();

Kullandığınızdan emin olun:

System.Drawing & using System.Drawing.Imaging;

1
Bu yaklaşım, görüntüyü, görüntünüzü görünür bir şekilde bozabilecek sıkıştırma artefaktları tanıtacak olan varsayılan sıkıştırma ayarlarına sahip bir jpeg olarak kaydeder.
Richard Ev

Yine, bitmap üzerinde Kaydet yöntemi yok.
Prescott Chartier

7

Sadece yapabileceğinize inanıyorum:

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

Daha basit:

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

-3

Bunu sadece bir satırda çok basit kullanın:

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

op, bu seçenekle ilgilenmediğini söyledi
Mauro Sampietro
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.