ビットマップをバイト配列に変換します


233

C#を使用して、Windowsのを変換するためのより良い方法があるBitmapbyte[]一時ファイルに保存し、使用して結果を読むよりはFileStream

回答:


418

いくつかの方法があります。

ImageConverter

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

これは多くのコードを必要としないので便利です。

メモリストリーム

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

これは、ファイルがディスクではなくメモリに保存されることを除いて、あなたがやっていることと同じです。さらに多くのコードがありますが、ImageFormatのオプションがあり、メモリまたはディスクへの保存の間に簡単に変更できます。

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


2
また、高速などの任意の中間memorystreamsせずにコピーする簡単なためbitmap.LockbitsとMarshal.Copyを使用することができます
deegee

4
このImageConverterメソッドは画像をPNGとして保存し、結果として巨大なファイルになることに注意してください。
スコリマ2014年

8
「using」を使用するときにストリームを閉じる必要はありません
LastTribunal

2
この配列がどのように構造化されているかについて誰かが私にもう少し情報を提供できますか?x = 0で始まり、すべてのyを循環してから、xをインクリメントしますか?そして、次のように保存します:[0,0,1,1,1,1,1,0,0,1,1]?
レイモンドティマーマンズ2017年

1
ImageConverter使用する.netの標準ではありませんMemoryStream
Alexandre

95

これには、MemoryStreamが役立ちます。あなたはそれを拡張メソッドに置くことができます:

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

あなたはちょうどそれを次のように使うことができます:

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

ImageConverterに関するprestomaniftoの回答に一部同意しません。 ImageConverterは使用しないでください。 技術的に問題はありませんが、オブジェクトからのボックス化/ボックス化解除を使用しているという事実は、.NETフレームワークの古い暗い場所からのコードであり、画像処理で使用するのは理想的ではないことを示しています(バイトに変換するのはやり過ぎです) []少なくとも)、特に次のことを考慮した場合。

私はImageConverter.Netフレームワークで使用されているコードを調べました。内部では、上記で提供したコードとほぼ同じコードを使用しています。新しいを作成し、を指定したときの形式でをMemoryStream保存しBitmap、配列を返します。ImageConverterを使用してクラスを作成する余分なオーバーヘッドをスキップするMemoryStream


美しい。そうするだろう!ただし、MemoryStreamを破棄する必要があると思いますが、更新しますか?
ジェレミー・マギー

回答を更新しました。選択した回答が示唆するように、ImageConverterを使用しない理由、および廃棄の追加についてのディスカッションがいくつかあります。
Christopher Currens、2011

拡張メソッドの素敵な使い方、私はそれが好きです!
デュードパスカロウ

3
+1は、ImageConverterを調べて、研究結果を報告するためのものです。しかし、あなたが発見したものは「ImageConverterを使用しないでください」という記述を保証するものではないと思います。それは間違いなく、バイト配列から画像へと逆方向に進む有用なサービスを提供します。また、「ImageConverterクラスを作成することによる余分なオーバーヘッド」は無視できると考えられ、使用回数に関係なく、1回だけ実行する必要があります。
RenniePet 2013年

1
ImageConverterは、画像のタイプを自動的に判別できるという点でも役に立ちました。たとえば、画像のバイト配列があるが、形式がわからない場合-ヘッダーを読み取ってそこからヒントを取得することもできますが、まあ、...(Image img =(Image)myImgConverter.ConvertFrom(byteImage))を使用してからimg.PixelFormatなどをチェックするのが簡単です...-もちろん、やりたいことに応じて
hello_earth

45

ビットマップデータをMarshal.Copyすることもできます。中間メモリストリームなどはなく、高速メモリコピー。これは、24ビットと32ビットの両方のビットマップで機能します。

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
こんにちは、私はこの方法を使用しましたが、このバイト配列を再び画像に変換することはできません。ビットマップbitmap1 = new Bitmap(new MemoryStream(array)); 無効なパラメータの例外をスローします。間違いはありませんか?
ハワード

1
こんにちは。コメントセクションが小さすぎて、完全なクリーンなコードを投稿できません。最も簡単な方法は、配列を固定することです:GCHandle handle = GCHandle.Alloc(bufferarray、GCHandleType.Pinned); 配列へのポインタを取得しますIntPtr iptr = Marshal.UnsafeAddrOfPinnedArrayElement(bufferarray、0); 次に、IntPtrを使用して新しいビットマップを作成します。bitmap = new Bitmap(width、height、(width * 4)、PixelFormat.Format32bppArgb、iptr); ただし、ビットマップ形式に適したビットマップ作成パラメーターを使用する必要があります。必ずクリーンアップしてください:iptr = IntPtr.Zero; handle.Free();
ディージー2013

3
バグは何ですか?私を含む多くのプログラマーがこのコードスタイルを使用しており、正常に動作します。
2013

4
@ mini-me-ビットマップの幅とビットマップのストライドを調べることをお勧めします。これは私のコードのバグではなく、Windowsがビットマップを処理する方法です。ストライドは、各行の終わりに32ビット境界で開始するために、各行の終わり(幅)に追加のデータを含めることができ、メモリのアライメントとパフォーマンスを向上させます。
2014年

3
バグではありません。 msdn.microsoft.com/en-us/library/...
deegee

16

画像をMemoryStreamに保存してから、バイト配列を取得します。

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

  Byte[] data;

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

    data = memoryStream.ToArray();
  }

画像にSaveメソッドがありません。
プレスコットシャルティエ

@PrescottChartier上記の例は、派生型から作業していることを前提としていますSystem.Drawing.Image (参照:docs.microsoft.com/en-us/dotnet/api/…
Chris Baxter

うん、そうだSystem.Drawing.Image does not exist。したがって、..いいえ、機能しません:(
Prescott Chartier

あなたは、私がここでやろうとしているかを見ることができます。 stackoverflow.com/questions/55084620/...
プレスコットシャルティエ

10

次のように、のMemoryStream代わりにを使用しますFileStream

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

あなたはおそらく望んでいるのToArrayではなくGetBuffer
vcsjones 2011

GetBufferは符号なしバイトの配列(バイト配列)を返します
Jeff Reddy

4
画像の一部ではないフィラーデータが含まれている可能性があります。docsから: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.したがって、fromのバイト配列GetBufferはイメージと未使用のバイトを返します。これにより、イメージが破損する可能性があります。
vcsjones 2011

1
知っておくと良い。コメントvcsをありがとう!
ジェフレディ2011

このアプローチでは、デフォルトの圧縮設定で画像をjpegとして保存します。これにより、画像が明らかに劣化する可能性のある圧縮アーティファクトが発生します。
Richard Ev 2015年

8

以下を試してください:

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

byte[] byteArray = stream.GetBuffer();

以下を使用していることを確認してください:

System.Drawing & using System.Drawing.Imaging;

1
このアプローチでは、デフォルトの圧縮設定で画像をjpegとして保存します。これにより、画像が明らかに劣化する可能性のある圧縮アーティファクトが発生します。
Richard Ev

繰り返しますが、ビットマップのSaveメソッドはありません。
プレスコットシャルティエ

7

私はあなたが単にやってもよいと信じています:

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


-3

非常に簡単にこれを1行で使用します。

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

opは彼がこのオプションに興味がないと言った
Mauro Sampietro
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.