画像をバイト配列に変換する最速の方法


106

デスクトップの画像をキャプチャして圧縮し、受信機に送信するリモートデスクトップ共有アプリケーションを作成しています。画像を圧縮するには、それをbyte []に​​変換する必要があります。

現在私はこれを使用しています:

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

しかし、ImageFormatに保存する必要があり、リソースも消費する(スローダウン)だけでなく、異なる圧縮結果が生成される可能性があるため、私は好きではありません。Marshal.Copyとmemcpyの使用について読んだのですが、それらを理解します。

それで、この目標を達成する他の方法はありますか?


MemoryStreamとImageの両方にdisposeメソッドがあります。MemoryLeakが発生する可能性があるため、それらをDisposeしていることを確認してください。
abc123 2013年

3
@ abc123:を破棄する必要はありませんMemoryStream。リモーティングで使用しない限り、完全に管理されたリソースです。これらのどちらの場合でも、リソースを破棄することは不適切です。
Jon Skeet 2013年

1
@JonSkeet興味深いですが、ベンチマークを行っていますか?.netがオブジェクトを解放する速度を確認するには?DataTableにも同様の引数があることを知っていますが、破棄が使用されたときにGarbageCollectorが割り当てられたメモリを収集する速度には、顕著な違いがあります。
abc123 2013年

@ abc123:本当にそうなるとは期待していません-ストリームを破棄しても配列には何も行われず、MemoryStreamにはファイナライザがありません(DataTableとは異なり、MarshalByValueComponentから継承されます)。
Jon Skeet 2013年

2
完全なソースコードを使用した最終的な解決策はありますか?
Kiquenet 2013年

回答:


39

それで、この目標を達成する他の方法はありますか?

あなたはバイト配列に画像を変換するために第持っているあなたはバイト配列にテキストを変換する際にエンコーディングを指定する必要が同じように-画像フォーマットを指定します。

圧縮アーティファクトが心配な場合は、ロスレスフォーマットを選択してください。CPUリソースが心配な場合は、圧縮を行わないフォーマットを選択してください。たとえば、ARGBピクセルのみを使用します。しかし、もちろんそれはより大きなバイト配列につながります。

圧縮を含むフォーマットを選択した場合、後でバイト配列を圧縮しても意味がないことに注意してください。有益な効果がないことはほぼ確実です。


12
「ロスレスフォーマットを選択する」よりも、imageIn.RawFormat再エンコードせずに生の画像バイトを保存する試みを選択できます。
Chris Fキャロル

52

画像のファイル形式を返すImageパラメータのRawFormatプロパティがあります。あなたは以下を試すかもしれません:

// extension method
public static byte[] imageToByteArray(this System.Drawing.Image image)
{
    using(var ms = new MemoryStream())
    {
        image.Save(ms, image.RawFormat);
        return ms.ToArray();
    }
}

9
MemoryStreamを破棄するか、このメソッドの本文をusing(){}ステートメントでラップすることをお勧めします
Neil.Allen

@ Neil.Allen私はここで新しいのですが、その理由を教えてください。
Khalil Khalaf 2016年

3
@FirstStep自分の後片付けをするので:)
Sinaesthetic

@Sinaestheticなるほど。そしてルーチンは、using(){}に実行したい関数を置くことです?
Khalil Khalaf

2
@FirstStep違います。より正確に:IDisposableを実装したオブジェクトを使用する場合は、それが完了したら必ずDispose()を呼び出して、関連付けられているすべてのリソースをクリーンアップする必要があります。using(){}ステートメントは、オブジェクトがそのステートメントのスコープ外になると、それを呼び出すだけです。つまり、あなたはできるかmyObject.Dispose()using(myObject){}どちらも同じことをしますが、usingステートメントは基本的にクリーンアップするスコープを作成します。
Sinaesthetic

14

ジョン・スキートが指摘した理由であなたが何か大きな利益を得られるかどうかはわかりません。ただし、TypeConvert.ConvertToメソッドをベンチマークして、現在のメソッドを使用した場合との比較を確認できます。

ImageConverter converter = new ImageConverter();
byte[] imgArray = (byte[])converter.ConvertTo(imageIn, typeof(byte[]));

タイプ「System.Byte []」のオブジェクトをタイプ「System.Drawing.Image」にキャストできません。
user123 2014年

14
public static byte[] ReadImageFile(string imageLocation)
    {
        byte[] imageData = null;
        FileInfo fileInfo = new FileInfo(imageLocation);
        long imageFileLength = fileInfo.Length;
        FileStream fs = new FileStream(imageLocation, FileMode.Open, FileAccess.Read);
        BinaryReader br = new BinaryReader(fs);
        imageData = br.ReadBytes((int)imageFileLength);
        return imageData;
    }

5
stackoverflow.comへようこそ。上記のコードサンプルが役立つ理由を説明する詳細を追加してください。それは完全に理解できないかもしれない他のSOユーザー向けです... stackoverflow.com/help/how-to-answer
Mack

これはファイルをバイトに変換するためのものですが、OPは描画オブジェクトをバイトに変換する必要がありました。描画オブジェクトは、必ずしもファイルシステムではなく、バイトの配列としてデータベースに格納できるため、前後に変換する必要があります。ただし、バイトに変換するFileStreamのファイルとしてはできません最初のアップロード。
vapcguy 2015年

これは、ファイルでこれを実行しようとしていたときに役立ちました。その関連として持っているのは良いです。
ジャスティン

5
public static class HelperExtensions
{
    //Convert Image to byte[] array:
    public static byte[] ToByteArray(this Image imageIn)
    {
        var ms = new MemoryStream();
        imageIn.Save(ms, System.Drawing.Imaging.ImageFormat.Png);
        return ms.ToArray();
    }

    //Convert byte[] array to Image:
    public static Image ToImage(this byte[] byteArrayIn)
    {
        var ms = new MemoryStream(byteArrayIn);
        var returnImage = Image.FromStream(ms);
        return returnImage;
    }
}

2

私が見つけることができる最も速い方法はこれです:

var myArray = (byte[]) new ImageConverter().ConvertTo(InputImg, typeof(byte[]));

役立つことを願っています


特にSystem.Windows.Controls.Imageオブジェクトがある場所でWPFを使用する場合は、これに注意してください。これらの1つをバイトに変換する必要があり、それをこの行にとして渡した場合InputImg、これは機能しません。それは期待しSystem.Drawing.Imageたオブジェクトを。
vapcguy
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.