常にコンテンツ タイプが含まれているとは限らず、ダウンロードするファイルの拡張子を提供しないサービスからいくつかの画像をダウンロードしています (うーん、尋ねないでください)。
.NET でイメージ形式を判断する最良の方法は何ですか?
これらのダウンロードされた画像を読み取るアプリケーションには、適切なファイル拡張子が必要です。
常にコンテンツ タイプが含まれているとは限らず、ダウンロードするファイルの拡張子を提供しないサービスからいくつかの画像をダウンロードしています (うーん、尋ねないでください)。
.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
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;
}
すべての画像形式は、初期バイトを特定の値に設定します。
jpg を特定する必要がある他のファイル形式に置き換えて、「jpg ファイル形式」を検索します。
Garth が推奨するように、多くのファイルのファイル タイプを示す「マジック ナンバー」のデータベースがあります。さまざまな種類のファイルを検出する必要がある場合は、ファイルを調べて必要な情報を見つけることをお勧めします。非常に多くのファイル タイプをカバーするためにこれを拡張する必要がある場合は、データベースを正しく使用するためのエンジンを実装する関連ファイル コマンドを参照してください (多くのファイル形式では簡単ではなく、ほぼ統計的なプロセスです)。
-アダム
アダムはまさに正しい方向を指しています。
ほぼすべてのファイルを検出する方法を知りたい場合はfile
、UNIX、Linux、または Mac OS X マシンのコマンドの背後にあるデータベースを調べてください。
file
は、「マジック ナンバー」のデータベース (Adam がリストした最初のバイト) を使用して、ファイルの種類を検出します。man file
マシン上のデータベースの場所を教えてくれます/usr/share/file/magic
。man 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色
幸運を!
画像の 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];
ストリームを System.IO.BinaryReader にロードしてみてください。
次に、必要な各画像形式の仕様を参照し、ヘッダーをバイト単位でロードして仕様と比較する必要があります。たとえば、PNG仕様は次のとおりです
追加: PNGの実際のファイル構造。