画像のファイルタイプを決定する
-
09-06-2019 - |
質問
コンテンツ タイプが必ずしも含まれておらず、ダウンロードしているファイルの拡張子も提供されないサービスから画像をダウンロードしています (ああ、聞かないでください)。
.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: 0xFF 0xD8
- PNG: 0x89 0x50 0x4E 0x47 0x0D 0x0A 0x1A 0x0A
- GIF: 「G」「I」「F」
「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];