Używając C #, czy jest lepszy sposób na konwersję systemu Windows Bitmap
na byte[]
niż zapisywanie do pliku tymczasowego i odczytywanie wyniku za pomocą FileStream
?
Używając C #, czy jest lepszy sposób na konwersję systemu Windows Bitmap
na byte[]
niż zapisywanie do pliku tymczasowego i odczytywanie wyniku za pomocą FileStream
?
Odpowiedzi:
Istnieje kilka sposobów.
ImageConverter
public static byte[] ImageToByte(Image img)
{
ImageConverter converter = new ImageConverter();
return (byte[])converter.ConvertTo(img, typeof(byte[]));
}
Ten jest wygodny, ponieważ nie wymaga dużo kodu.
Strumień pamięci
public static byte[] ImageToByte2(Image img)
{
using (var stream = new MemoryStream())
{
img.Save(stream, System.Drawing.Imaging.ImageFormat.Png);
return stream.ToArray();
}
}
Ten jest równoważny z tym, co robisz, z wyjątkiem tego, że plik jest zapisywany w pamięci zamiast na dysku. Chociaż więcej kodu masz opcję ImageFormat i można go łatwo modyfikować między zapisywaniem w pamięci lub na dysku.
ImageConverter
metoda zapisze obraz jako Png, co spowoduje OGROMNE pliki.
ImageConverter
nie jest standardem .net, którego możesz użyćMemoryStream
MemoryStream może być pomocne w tej sprawie. Możesz umieścić go w metodzie rozszerzenia:
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();
}
}
}
Możesz po prostu użyć go w następujący sposób:
var image = new Bitmap(10, 10);
// Draw your image
byte[] arr = image.ToByteArray(ImageFormat.Bmp);
Częściowo nie zgadzam się z odpowiedzią prestomanifto dotyczącą ImageConverter. Nie używaj ImageConverter. Nie ma w tym nic złego pod względem technicznym, ale sam fakt, że używa on boksowania / rozpakowywania z obiektu, mówi mi, że to kod ze starych ciemnych miejsc .NET Framework i nie jest idealny do użycia z przetwarzaniem obrazu (to przesada w przypadku konwersji na bajt [] przynajmniej), zwłaszcza jeśli weźmiesz pod uwagę następujące kwestie.
Przyjrzałem się ImageConverter
kodowi używanemu przez platformę .Net i wewnętrznie używa kodu prawie identycznego z tym, który podałem powyżej. Tworzy nowy MemoryStream
, zapisuje Bitmap
w jakimkolwiek formacie, w jakim był, gdy go podałeś, i zwraca tablicę. Pomiń dodatkowe koszty związane z tworzeniem ImageConverter
klasy za pomocąMemoryStream
Możesz także po prostu Marshal. Skopiować dane mapy bitowej. Brak pośredniego memorystream itp. I szybka kopia pamięci. Powinno to działać zarówno na bitmapach 24-bitowych, jak i 32-bitowych.
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);
}
}
.
Zapisz obraz w MemoryStream, a następnie chwyć tablicę bajtów.
http://msdn.microsoft.com/en-us/library/ms142148.aspx
Byte[] data;
using (var memoryStream = new MemoryStream())
{
image.Save(memoryStream, ImageFormat.Bmp);
data = memoryStream.ToArray();
}
System.Drawing.Image
(patrz: docs.microsoft.com/en-us/dotnet/api/... )
System.Drawing.Image does not exist
. Więc .. nie, nie działa :(
Użyj MemoryStream
zamiast a FileStream
, jak poniżej:
MemoryStream ms = new MemoryStream();
bmp.Save (ms, ImageFormat.Jpeg);
byte[] bmpBytes = ms.ToArray();
ToArray
, nie GetBuffer
.
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.
teraz tablica bajtów z GetBuffer
zwróci obraz plus nieużywane bajty, co prawdopodobnie spowoduje uszkodzenie obrazu.
Spróbuj wykonać następujące czynności:
MemoryStream stream = new MemoryStream();
Bitmap bitmap = new Bitmap();
bitmap.Save(stream, ImageFormat.Jpeg);
byte[] byteArray = stream.GetBuffer();
Upewnij się, że używasz:
System.Drawing & using System.Drawing.Imaging;
MemoryStream ms = new MemoryStream();
yourBitmap.Save(ms, ImageFormat.Bmp);
byte[] bitmapData = ms.ToArray();
Prościej:
return (byte[])System.ComponentModel.TypeDescriptor.GetConverter(pImagen).ConvertTo(pImagen, typeof(byte[]))
Bardzo proste użycie tego tylko w jednym wierszu:
byte[] imgdata = File.ReadAllBytes(@"C:\download.png");