C# と VB.NET の質問掲示板

ASP.NET、C++/CLI、Java 何でもどうぞ

C# と VB.NET の入門サイト

Re[1]: バイナリのヘッダから画像の拡張子を調べる方法


(過去ログ 128 を表示中)

[トピック内 5 記事 (1 - 5 表示)]  << 0 >>

■76221 / inTopicNo.1)  バイナリのヘッダから画像の拡張子を調べる方法
  
□投稿者/ 久保田 (1回)-(2015/06/12(Fri) 14:40:43)

分類:[C#] 

C#

現在タイトルにも書いた方法のやり方がわからなく悩んでおります。
選択した画像からbyte配列を取得するところまではできたのですが
そこからbyte配列のヘッダをどのように扱えば拡張子を調べれるかわからず迷っています
よければご教授お願いしたいです。よろしくお願いします
引用返信 編集キー/
■76222 / inTopicNo.2)  Re[1]: バイナリのヘッダから画像の拡張子を調べる方法
□投稿者/ 魔界の仮面弁士 (381回)-(2015/06/12(Fri) 15:10:35)
No76221 (久保田 さん) に返信
> 選択した画像からbyte配列を取得するところまではできたのですが

これは、File.ReadAllBytes メソッド等で読み取った
画像ファイルの byte[] を指しているのでしょうか?

それとも、画像ファイルのヘッダー部分を含んでいない、
Bitmap.GetPixel や .LockBits などで得た画素情報のことでしょうか?


> そこからbyte配列のヘッダをどのように扱えば拡張子を調べれるかわからず迷っています
拡張子、というか画像フォーマットですね。


方法の一つとしては、画像データを Image.FromStream で読み取って、
その RawFormat プロパティを見るという手法があります。


string extension = null;
string formatName = null;
Guid rawFormat = default(Guid);

using (var reader = new MemoryStream(bin))
using (var img = Image.FromStream(reader))
{
  rawFormat = img.RawFormat.Guid;
}

var codec = ImageCodecInfo.GetImageDecoders()
 .FirstOrDefault<ImageCodecInfo>(c => c.FormatID == rawFormat);
if(codec != null)
{
  extension = codec.FilenameExtension;
  formatName = codec.FormatDescription;
}



もう一つは、その byte 配列の中身を自分で精査する手法です。
たとえば…

Bitmap なら先頭 2 バイトが 42,4D (文字列 "BM")
Jpeg なら、先頭 3 バイトが FF,D8,FF
PNG なら、先頭 8 バイトが 89,50,4E,47,0D,0A,1A,0A
GIF なら、先頭 6 バイトが 47,49,46,38,39,61 (文字列 "GIF89a")
または 先頭 6 バイトが 47,49,46,38,37,61 (文字列 "GIF87a")
引用返信 編集キー/
■76223 / inTopicNo.3)  Re[1]: バイナリのヘッダから画像の拡張子を調べる方法
□投稿者/ 774RR (266回)-(2015/06/12(Fri) 15:12:31)
質問の意味がいまいちよくわからないんだけど
拡張子ってのはファイル名の一部だからファイル内容から推測するものではない。

ファイル内容から、このファイルの形式がなにかを推測する(結果的に JPG であるとか PNG であるとか)
ということなら・・・ファイルフォーマットとかマジックナンバーとかの用語を検索。

BITMAP (.BMP) ならファイルの0バイト目から BM とか
JPEG ならファイルの6バイト目から JFIF とか
PNG ならファイルの0バイト目から 0x89 PNG とか

UNIX 系 だと file ってコマンドがあってファイル内容が magic に合致したらその旨表示してくれる。

引用返信 編集キー/
■76224 / inTopicNo.4)  Re[1]: バイナリのヘッダから画像の拡張子を調べる方法
□投稿者/ WebSurfer (598回)-(2015/06/12(Fri) 15:29:14)
No76221 (久保田 さん) に返信

他の方の回答とダブリますが・・・

拡張子ではなくて(バイナリデータには拡張子は含まれていません)、画像の種類(jpeg,
png, gif など)を判別したいということであれば、決まったフォーマットがあるそうです
ので、それをチェックして判別してはいかがでしょう?

http://www.yomotsu.net/wp/?p=504
PNG, GIF, JPEG のバイナリーデータなどについて

バイナリデータのヘッダを正規表現でチェック
http://siisise.net/jpeg.html

フォーマット辞典
http://siisise.net/format.html

引用返信 編集キー/
■76225 / inTopicNo.5)  Re[2]: バイナリのヘッダから画像の拡張子を調べる方法
□投稿者/ 魔界の仮面弁士 (382回)-(2015/06/12(Fri) 16:42:43)
No76222 (魔界の仮面弁士)
> Jpeg なら、先頭 3 バイトが FF,D8,FF

No76223 (774RR さん)
> JPEG ならファイルの6バイト目から JFIF とか


JPEG 判定の説明が 2 通り提示されたので、一応追加説明。


---

JPEG は、「マーカー2バイト|セグメントサイズ2バイト|セグメントデータ…」形式の
セグメントの繰り返しで構成されています。セグメントにはいろいろな種類がありますが、
先頭 2 バイトのマーカーで識別されます。各マーカーの 1 バイト目は、0xFF 固定です。


一般的な JFIF フォーマットの場合は、こんな感じで並びます。
デジカメ等で使われる EXIF も、JFIF の派生バージョンなので基本的には同様。


FF,D8 : <Start Of Image> ファイルの先頭は必ずコレ
FF,E0 : <APP0 マーカー> 解像度情報など 2番目はこれ
 xx,xx : このセグメントのデータ長
 4A,46,49,46,00 : 文字列 "JFIF\0"
 xx,xx : JFIFバージョン番号(1.01 なら 0x0101、1.02 なら 0x0102)
 xx : 解像度の単位(0=なし、1=ピクセル/インチ、2=ピクセル/センチメートル)
 xx,xx : 水平解像度
 xx,xx : 垂直解像度
 xx : サムネイルの幅(サムネイルが無ければ0)
 xx : サムネイルの高さ(サムネイルが無ければ0)
 可変長 : サムネイルイメージデータ(24bitRGB)
FF,DB : <量子化テーブル>
 xx,xx : このセグメントのデータ長
 xx,xx : 量子化因子の精度(0=8bit、1=16bit)
 xx,xx : テーブル識別子(0〜3)
 可変長 : 量子化因子(QF00〜QF77)


先頭には Start Of Image セグメントがあり、次に APP0 セグメントが続きますが、
以降のセグメントの順番は決まっていません。
APP0(FF,E0) の次に 量子化テーブル(FF,DB) が来る場合もあれば、デジカメ画像などの
Exif 情報を持った APP1 セグメント(FF,E1) が続く場合もあります。


でもって、APP0 マーカー内にある ゼロ終端文字列「JFIF」を読み取るのが、
> JPEG ならファイルの6バイト目から JFIF とか
という判定方法というわけですね。

一方で、APP0 セグメントを後ろに配置しても読めてしまう処理系もあります。
そのようなものにも対応させる場合には、処理を端折って、
先頭 2 バイトの <Start Of Image> および 後続セグメントのマーカーフラグ(FF) を
> Jpeg なら、先頭 3 バイトが FF,D8,FF
と読み取って判定することもできます。



ちなみに、JPEG 2000 の場合は、「先頭3バイトが FF,4F,FF」として判断できます。

JPEG 2000 の場合は、ファイル先頭が SOI(FF,D8)ではなく、
 FF,4F : <Start Of CodeStream>
で始まります。この後に続くセグメントは、やはり画像によってまちまちです。
イメージ&タイルサイズ(FF,51)となることもあれば、
タイルパート (FF,90)が来ることもあります。
引用返信 編集キー/


トピック内ページ移動 / << 0 >>

このトピックに書きこむ

過去ログには書き込み不可

管理者用

- Child Tree -