質問

コンテンツ タイプが必ずしも含まれておらず、ダウンロードしているファイルの拡張子も提供されないサービスから画像をダウンロードしています (ああ、聞かないでください)。

.NET で画像形式を決定する最良の方法は何ですか?

これらのダウンロードされたイメージを読み取るアプリケーションは、適切なファイル拡張子を持っている必要があります。そうしないと、とんでもないことが起こります。

役に立ちましたか?

解決

おそらくより簡単なアプローチは、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

他のヒント

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

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

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

-アダム

System.Drawing を参照したり、オブジェクト Image を不要に作成したりせずに、以下のコードを使用できます。また、使用することもできます アレックス System.IO のストリームと参照がなくても解決できます。

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

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

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

file は、「マジックナンバー」(アダムがリストした最初のバイト)のデータベースを使用して、ファイルのタイプを検出します。 man file あなたのマシン上のデータベースの場所を教えてくれます。 /usr/share/file/magic. man magic それを教えてくれるでしょう フォーマット.

データベースに表示された内容に基づいて独自の検出コードを作成することも、事前にパッケージ化されたライブラリ (例: Python-マジック)、または — あなたがそうであれば 本当に 冒険的 — の .NET バージョンを実装する libmagic. 。見つからなかったので、他のメンバーが指摘してくれることを願っています。

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

# PNG [Portable Network Graphics, or "PNG's Not GIF"] images
# (Greg Roelofs, newt@uchicago.edu)
# (Albert Cahalan, acahalan@cs.uml.edu)
#
# 137 P N G \r \n ^Z \n [4-byte length] H E A D [HEAD data] [HEAD crc] ...
#
0       string          \x89PNG         PNG image data,
>4      belong          !0x0d0a1a0a     CORRUPTED,
>4      belong          0x0d0a1a0a
>>16    belong          x               %ld x
>>20    belong          x               %ld,
>>24    byte            x               %d-bit
>>25    byte            0               grayscale,
>>25    byte            2               \b/color RGB,
>>25    byte            3               colormap,
>>25    byte            4               gray+alpha,
>>25    byte            6               \b/color RGBA,
#>>26   byte            0               deflate/32K,
>>28    byte            0               non-interlaced
>>28    byte            1               interlaced
1       string          PNG             PNG image data, CORRUPTED

# GIF
0       string          GIF8            GIF image data
>4      string          7a              \b, version 8%s,
>4      string          9a              \b, version 8%s,
>6      leshort         >0              %hd x
>8      leshort         >0              %hd
#>10    byte            &0x80           color mapped,
#>10    byte&0x07       =0x00           2 colors
#>10    byte&0x07       =0x01           4 colors
#>10    byte&0x07       =0x02           8 colors
#>10    byte&0x07       =0x03           16 colors
#>10    byte&0x07       =0x04           32 colors
#>10    byte&0x07       =0x05           64 colors
#>10    byte&0x07       =0x06           128 colors
#>10    byte&0x07       =0x07           256 colors

幸運を!

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

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

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

クラス システム.図面.イメージ 財産を持っている 生フォーマット タイプの System.Drawing.Imaging.ImageFormat 財産を持っているもの ガイド これはプロパティと同等です フォーマットID クラスの System.Drawing.Imaging.ImageCodecInfo, 、これが辞書から 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];

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

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

追加した:実際の ファイル構造 PNGの場合。

ライセンス: CC-BY-SA帰属
所属していません StackOverflow
scroll top