50

常にコンテンツ タイプが含まれているとは限らず、ダウンロードするファイルの拡張子を提供しないサービスからいくつかの画像をダウンロードしています (うーん、尋ねないでください)。

.NET でイメージ形式を判断する最良の方法は何ですか?

これらのダウンロードされた画像を読み取るアプリケーションには、適切なファイル拡張子が必要です。

4

6 に答える 6

55

おそらくより簡単な方法は、 Image.FromFile() を使用してから RawFormat プロパティを使用することです。これは、次のように、最も一般的な形式のヘッダーのマジック ビットを既に認識しているためです。

Image i = Image.FromFile("c:\\foo");
if (System.Drawing.Imaging.ImageFormat.Jpeg.Equals(i.RawFormat)) 
    MessageBox.Show("JPEG");
else if (System.Drawing.Imaging.ImageFormat.Gif.Equals(i.RawFormat))
    MessageBox.Show("GIF");
//Same for the rest of the formats
于 2008-09-11T06:11:18.593 に答える
28

System.Drawing を参照せずに、オブジェクト Image を不要に作成することなく、以下のコードを使用できます。また、System.IO のストリームと参照がなくてもAlexソリューションを使用できます。

public enum ImageFormat
{
    bmp,
    jpeg,
    gif,
    tiff,
    png,
    unknown
}

public static ImageFormat GetImageFormat(Stream stream)
{
    // see http://www.mikekunz.com/image_file_header.html
    var bmp = Encoding.ASCII.GetBytes("BM");     // BMP
    var gif = Encoding.ASCII.GetBytes("GIF");    // GIF
    var png = new byte[] { 137, 80, 78, 71 };    // PNG
    var tiff = new byte[] { 73, 73, 42 };         // TIFF
    var tiff2 = new byte[] { 77, 77, 42 };         // TIFF
    var jpeg = new byte[] { 255, 216, 255, 224 }; // jpeg
    var jpeg2 = new byte[] { 255, 216, 255, 225 }; // jpeg canon

    var buffer = new byte[4];
    stream.Read(buffer, 0, buffer.Length);

    if (bmp.SequenceEqual(buffer.Take(bmp.Length)))
        return ImageFormat.bmp;

    if (gif.SequenceEqual(buffer.Take(gif.Length)))
        return ImageFormat.gif;

    if (png.SequenceEqual(buffer.Take(png.Length)))
        return ImageFormat.png;

    if (tiff.SequenceEqual(buffer.Take(tiff.Length)))
        return ImageFormat.tiff;

    if (tiff2.SequenceEqual(buffer.Take(tiff2.Length)))
        return ImageFormat.tiff;

    if (jpeg.SequenceEqual(buffer.Take(jpeg.Length)))
        return ImageFormat.jpeg;

    if (jpeg2.SequenceEqual(buffer.Take(jpeg2.Length)))
        return ImageFormat.jpeg;

    return ImageFormat.unknown;
}
于 2012-09-16T22:01:44.430 に答える
22

すべての画像形式は、初期バイトを特定の値に設定します。

jpg を特定する必要がある他のファイル形式に置き換えて、「jpg ファイル形式」を検索します。

Garth が推奨するように、多くのファイルのファイル タイプを示す「マジック ナンバー」のデータベースがあります。さまざまな種類のファイルを検出する必要がある場合は、ファイルを調べて必要な情報を見つけることをお勧めします。非常に多くのファイル タイプをカバーするためにこれを拡張する必要がある場合は、データベースを正しく使用するためのエンジンを実装する関連ファイル コマンドを参照してください (多くのファイル形式では簡単ではなく、ほぼ統計的なプロセスです)。

-アダム

于 2008-09-11T05:57:01.657 に答える
8

アダムはまさに正しい方向を指しています。

ほぼすべてのファイルを検出する方法を知りたい場合はfile、UNIX、Linux、または Mac OS X マシンのコマンドの背後にあるデータベースを調べてください。

fileは、「マジック ナンバー」のデータベース (Adam がリストした最初のバイト) を使用して、ファイルの種類を検出します。man fileマシン上のデータベースの場所を教えてくれます/usr/share/file/magicman magicその形式を教えてくれます。

データベースに表示される内容に基づいて独自の検出コードを作成するか、事前にパッケージ化されたライブラリ ( python-magicなど) を使用するか、または (本当に冒険好きなら)の .NET バージョンを実装することができますlibmagic。見つけられなかったので、別のメンバーが指摘してくれることを願っています。

手元に UNIX マシンがない場合、データベースは次のようになります。

# PNG [Portable Network Graphics、または「PNG は GIF ではありません」] 画像
#(グレッグ・ローロフス、newt@uchicago.edu)
#(アルバート・カハラン、acahalan@cs.uml.edu)
#
#137 PNG\r\n^Z\n【4バイト長】HEAD【HEADデータ】【HEAD crc】…
#
0 文字列 \x89PNG PNG 画像データ、
>4 所属 !0x0d0a1a0a 破損、
>4 所属 0x0d0a1a0a
>>16 所属 x %ld x
>>20 所属 x %ld,
>>24 バイト x %d ビット
>>25 バイト 0 グレースケール、
>>25 バイト 2 \b/カラー RGB,
>>25 バイト 3 カラーマップ、
>>25 バイト 4 グレー + アルファ、
>>25 バイト 6 \b/色 RGBA,
#>>26 バイト 0 deflate/32K,
>>28 バイト 0 ノンインターレース
>>28 バイト 1 インターレース
1 文字列 PNG PNG 画像データ、破損

#GIF
0文字列 GIF8 GIF画像データ
>4 文字列 7a \b、バージョン 8%s、
>4 文字列 9a \b、バージョン 8%s、
>6 レショート >0 %hd x
>8 レショート >0 %hd
#>10 バイト &0x80 カラー マップ、
#>10バイト&0x07 =0x00 2色
#>10バイト&0x07 =0x01 4色
#>10バイト&0x07 =0x02 8色
#>10バイト&0x07 =0x03 16色
#>10バイト&0x07 =0x04 32色
#>10バイト&0x07 =0x05 64色
#>10バイト&0x07 =0x06 128色
#>10バイト&0x07 =0x07 256色

幸運を!

于 2008-09-11T06:01:23.487 に答える
3

画像の MIMETYPE をプログラムで判別する方法があります。

クラスSystem.Drawing.Imaging.ImageCodecInfoがあります。

このクラスには、プロパティMimeTypeおよびFormatIDがあります。また、すべての画像エンコーダーのコレクションを返すGetImageEncodersメソッドもあります。フォーマット ID で索引付けされた MIME タイプの辞書を作成するのは簡単です。

クラスSystem.Drawing.Imageには、クラスSystem.Drawing.Imaging.ImageCodecInfoのプロパティFormatIDと同等のプロパティGuidを持つタイプSystem.Drawing.Imaging.ImageFormatのプロパティRawFormatがあり、これは辞書から MIMETYPE を取得するための鍵です。

例:

MIME タイプの辞書を作成する静的メソッド

static Dictionary<Guid, string> GetImageFormatMimeTypeIndex()
{
  Dictionary<Guid, string> ret = new Dictionary<Guid, string>();

  var encoders = System.Drawing.Imaging.ImageCodecInfo.GetImageEncoders();

  foreach(var e in encoders)
  {
    ret.Add(e.FormatID, e.MimeType);
  }

  return ret;
}

使用する:

Dictionary<Guid, string> mimeTypeIndex = GetImageFormatMimeTypeIndex();

FileStream imgStream = File.OpenRead(path);
var image = System.Drawing.Image.FromStream(imgStream);
string mimeType = mimeTypeIndex[image.RawFormat.Guid];
于 2012-08-21T09:18:22.977 に答える
0

ストリームを System.IO.BinaryReader にロードしてみてください。

次に、必要な各画像形式の仕様を参照し、ヘッダーをバイト単位でロードして仕様と比較する必要があります。たとえば、PNG仕様は次のとおりです

追加: PNGの実際のファイル構造。

于 2008-09-11T05:54:37.573 に答える