CでEXIFジオタグを使用する#

ジオタギングプログラムを終了した後、同じ記事を読む人が少なくなるように、この記事を書くというアイデアを得ました。これらの問題に関する賢明な情報があまりないためです。

そのため、 ジオタグまたはEXIFが何であるかを説明するつもりはありません。Wikipediaでそれについて読むことができます。 しかし、EXIFでデータを読み書きするプログラムをC#で作成する方法を教えます。 私の意見では、最も簡単な方法はJpegBitmapDecoderを使用することなので、写真のメタデータを使用します。このためには、いくつかのモジュールを接続する必要があります

using System.IO;

using System.Globalization;

using System.Windows.Media.Imaging;




* This source code was highlighted with Source Code Highlighter .






開始するには、写真ファイルを開くだけです:

FileStream Foto = File .Open(s, FileMode .Open, FileAccess.Read); // s

BitmapDecoder decoder = JpegBitmapDecoder.Create(Foto, BitmapCreateOptions.IgnoreColorProfile, BitmapCacheOption.Default); //"" decoder

BitmapMetadata TmpImgEXIF = (BitmapMetadata)decoder.Frames[0].Metadata.Clone(); //




* This source code was highlighted with Source Code Highlighter .






多くの場合、写真の日付と時刻を取得する必要があります。 EXIF仕様を見るといくつかの日付(写真の撮影、ファイルの作成、デジタル化、GPSなど)が保存されており、カメラが記録したものと無視したものはまだ明確ではありません。 しかし、実際にはこれを気にしないでください-ここではすべてが簡単です。 ビットマップメタデータ

撮影の日付と時刻、およびその他のパラメーター(カメラモデルなど)を取得するためのプロパティが含まれます。

DateTime DateOfShot = Convert .ToDateTime(TmpImgEXIF.DateTaken);



* This source code was highlighted with Source Code Highlighter .






では、ジオタグレコードに直接行きましょう。 (EXIFだけでなく)メタデータを操作するために、BitmapMetadataにはSetQueryメソッドGetQueryメソッドが含まれています 。 クエリ文字列をパラメーターとして受け取り、読み取りまたは書き込みを行うメタデータフィールドを決定します。 フィールドを削除するためのRemoveQueryもあります。 簡単なものから始めましょう。北緯があることをEXIFに追加します。 EXIFでは、ID = 1のGPSセクションフィールドに対応し、C#では、要求は「/ app1 / ifd / gps / {ushort = 1}」(これらの要求は後で取得します)で、データタイプは文字列です。 北緯が「N」、南が「S」の場合:

TmpImgEXIF.SetQuery( "/app1/ifd/gps/{ushort=1}" , "N" );



* This source code was highlighted with Source Code Highlighter .






同様に経度の場合:

TmpImgEXIF.SetQuery( "/app1/ifd/gps/{ushort=3}" , "E" );



* This source code was highlighted with Source Code Highlighter .






バージョンは2.2.0.0になります。

TmpImgEXIF.SetQuery( "/app1/ifd/gps/{ushort=0}" , "2.2.0.0" );



* This source code was highlighted with Source Code Highlighter .






高度になりました-これはオプションのパラメーターですが、その例ではRationalタイプの使用を検討します。 EXIF仕様を開くと海抜高度がRational形式で保存されていることがわかります。 このタイプは実数を単純な分数として表現するため、182.053は182053/1000(または1820530/10000)と記述されます。 C#でこのタイプを使用するには、 ulongタイプを選択し、分子を格納するために下位4バイトを使用し、分母に上位4バイトを使用できます。 以下は、doubleをRationalに変換するための関数です。

private ulong rational( double a)

{

uint denom = 1000;

uint num = ( uint )(a * denom);

ulong tmp;

tmp = ( ulong )denom << 32;

tmp |= ( ulong )num;

return tmp;

}




* This source code was highlighted with Source Code Highlighter .






95.3mの高さを記録しましょう(EXIFでは、海抜からの高さはメートル単位で保存されますが、フィートで保存される.pltトラックとは対照的です)。

TmpImgEXIF.SetQuery( "/app1/ifd/gps/{ushort=2}" , rational(95.3));



* This source code was highlighted with Source Code Highlighter .






さて、今度は緯度と経度を追加します。 度、分、秒、秒の小数部を表す3つのRationalの形式で保存されます。 度と分は整数で保存され(つまり、分母は1ですが、これは前提条件ではありません)、秒は実数です。 例:50⁰30'12.345″。 C#では、これら3つの数値を組み合わせて配列にする必要があります。 地理的な緯度の記録の例を次に示します。

ulong [] t = { rational(50), rational(30), rational(12.345) };

TmpImgEXIF.SetQuery( "/app1/ifd/gps/{ushort=2}" , t);




* This source code was highlighted with Source Code Highlighter .






および経度:

TmpImgEXIF.SetQuery( "/app1/ifd/gps/{ushort=4}" , t);



* This source code was highlighted with Source Code Highlighter .






まあ、それがおそらくすべてです。 トラック、タグ、インターネットサービスなどのファイルから取得した度と度の小数の形式から座標を変換する必要がある場合があります。そのような形式は作業に便利であるためですが、このような変換に問題はないはずです。 念のため、翻訳式は次のとおりです。

Degree = Math .Floor( value );

Minute = Math .Floor((( value - Math .Floor( value )) * 60.0));

Second = ((( value - Math .Floor( value )) * 60.0) - Math .Floor((( value - Math .Floor( value )) * 60.0))) * 60;




* This source code was highlighted with Source Code Highlighter .






したがって、新しいエントリが追加されたBitmapMetadataオブジェクトがあります(何かが既に書き留められている場合は、自動的に新しい値に置き換えられます)。 次に、最初のファイルのメタデータ以外のすべてを転送する新しいスナップショットファイルを作成し、変更したメタデータを取得します。

JpegBitmapEncoder Encoder = new JpegBitmapEncoder(); // Jpeg

Encoder.Frames.Add(BitmapFrame.Create(decoder.Frames[0], decoder.Frames[0].Thumbnail, TmpImgEXIF, decoder.Frames[0].ColorContexts)); // ( )

string NewFileName = s + "+GeoTag.jpg" ; // +GeoTag.jpg

using ( Stream jpegStreamOut = File .Open(NewFileName, FileMode .CreateNew, FileAccess.ReadWrite)) //

{

Encoder.Save(jpegStreamOut); //

}

Foto.Close(); //



* This source code was highlighted with Source Code Highlighter .






これで新しいjpegファイルができましたが、ジオタグがあります。 ソースファイルと新しいファイルのサイズは大幅に異なる可能性があることに注意してください。これは、画像圧縮のさまざまな方法とパラメーターによるものです。 SetQueryメソッドとGetQueryメソッドを使用して、EXIFフィールド(タグ)を操作できます。 GetQueryは同様の方法で機能します-クエリ文字列を受け入れ、どのタイプの値を返すか-EXIF 仕様で調べます。 どのリクエスト、どのパラメーターに答えるかは、 こちらで確認できます 。 たとえば、日付を読み取る機能:

GetQuery( "/app1/ifd/exif:{uint=36867}" );



* This source code was highlighted with Source Code Highlighter .






この例に示すよう 、クエリを使用できます。



All Articles