トップページ > 記事閲覧
Exif情報の取得方法
名前:KKK 日時: 2016/11/11 09:46

ある画像からGPS情報を読み取り、読み取った値をプログラム内での計算に使いたいと思っています。 しかし、画像のexif情報をどうやって読み取るのかがわかりません。 もし、このライブラリでできそうであったら、方法を教えてください。
メンテ

Page: 1 |

Re: Exif情報の取得方法 ( No.1 )
名前:管理人 日時:2016/11/13 17:32

「ある画像」とはJPEG形式のファイルのことでしょうか?
メンテ
Re: Exif情報の取得方法 ( No.2 )
名前:KKK 日時:2016/11/14 12:29

はい。その通りです。
メンテ
Re: Exif情報の取得方法 ( No.3 )
名前:管理人 日時:2016/11/15 01:10

ご返答ありがとうございます Exif情報を構造体の形で取得できるようなものを実装しようと思ったのですが、 情報の種類が多すぎたので断念し、とりあえず Exifのバイナリを取得できるだけの 関数をDXライブラリに追加しました // JPEGファイルの Exif情報を取得する // ExifBuffer を NULL に渡すと戻り値の情報のサイズのみ取得できます // 戻り値 -1:エラー -1以外:Exif情報のサイズ int ReadJpegExif( char *JpegFilePath, BYTE *ExifBuffer, size_t ExifBufferSize ) ; この関数を追加したバージョンをこちらにアップしましたので、よろしければダウンロードしてください m(_ _)m https://dxlib.xsrv.jp/temp/DxLibVCTest.exe // VisualC++ 用 https://dxlib.xsrv.jp/temp/DxLibBCCTest.exe // BorlandC++ 用 https://dxlib.xsrv.jp/temp/DxLibGCC_DevCppTest.exe // Dev-C++ 用 https://dxlib.xsrv.jp/temp/DxLibGCC_MinGWTest.exe // MinGW 用 https://dxlib.xsrv.jp/temp/DxLibDotNet.zip // .NET用 https://dxlib.xsrv.jp/temp/DxLibMakeTest.exe // ソース (中身を既存のライブラリのファイルに上書きして、BCCをお使いの 場合は『再構築』を、VCをお使いの場合は『リビルド』を、 Dev-C++をお使いの方は「Rebuild All(Ctrl+F11)」をして下さい) そして、ReadJpegExif を使用して Exif情報の中に含まれる GPS の緯度、経度、高度の情報を 取得するサンプルプログラムを組んでみましたので、よろしければご覧ください #include "DxLib.h" BYTE Exif[ 0xffff ] ; DWORD ExifSize ; int is_motorola ; struct ExifGPSInfo { char GPSLatitudeRef[ 2 ] ; // 緯度の南北( N or S ) int GPSLatitude[ 3 ][ 2 ] ; // 緯度(度、分、秒) char GPSLongitudeRef[ 2 ] ; // 経度の東西( E or W ) int GPSLongitude[ 3 ][ 2 ] ; // 経度(度、分、秒) char GPSAltitudeRef[ 2 ] ; // 高度の基準 int GPSAltitude[ 2 ] ; // 高度(m) } ; #define GET_BYTE( off ) Exif[ (off) + 0 + 6 ] #define GET_WORD( off ) \ ( is_motorola ? \ ( ( Exif[ (off) + 0 + 6 ] << 8 ) | ( Exif[ (off) + 1 + 6 ] ) ) :\ ( ( Exif[ (off) + 1 + 6 ] << 8 ) | ( Exif[ (off) + 0 + 6 ] ) ) ) #define GET_DWORD( off ) \ ( is_motorola ? \ ( ( Exif[ (off) + 0 + 6 ] << 24 ) | ( Exif[ (off) + 1 + 6 ] << 16 ) | ( Exif[ (off) + 2 + 6 ] << 8 ) | ( Exif[ (off) + 3 + 6 ] ) ) :\ ( ( Exif[ (off) + 3 + 6 ] << 24 ) | ( Exif[ (off) + 2 + 6 ] << 16 ) | ( Exif[ (off) + 1 + 6 ] << 8 ) | ( Exif[ (off) + 0 + 6 ] ) ) ) #define TYPE_NUM (11) DWORD TypeSize[ TYPE_NUM ] = { 0, // 0 : 未定義 1, // 1 : BYTE (8bit unsigned integer) 1, // 2 : ASCII (NULLで終わる文字列) 2, // 3 : SHORT (16bit unsigned integer) 4, // 4 : LONG (32bit unsigned integer) 8, // 5 : RATIONAL (2つのLONGの比; unsigned double) 0, // 6 : 未定義 1, // 7 : Undefined (8bit値) 0, // 8 : 未定義 4, // 9 : SLONG (32bit signed integer) 8, // 10 : SRATIONAL (2つのSLONGの比; signed double) } ; // 指定番号のタグを探す DWORD SearchTag( DWORD Offset, WORD Tag, DWORD NumberOfTags ) { for(;;) { // 残りデータのサイズをチェック if( Offset > ExifSize - 18 ) { return 0xffffffff ; } // GPS IFD へのポインタタグだったらループから抜ける if( GET_WORD( Offset ) == Tag ) { return Offset ; } // ディレクトリエントリを全て調べてなかったら終了 NumberOfTags-- ; if( NumberOfTags == 0 ) { return 0xffffffff ; } // 調べるオフセットを進める Offset += 12 ; } } // タグの情報を取得する int GetTagInfo( DWORD Offset, DWORD NumberOfTags, WORD Tag, BYTE *DataBuffer ) { DWORD TagOffset ; WORD Type ; DWORD DataNum ; DWORD DataSize ; DWORD DataOffset ; DWORD i ; TagOffset = SearchTag( Offset, Tag, NumberOfTags ) ; if( TagOffset == 0xffffffff ) { return -1 ; } Type = GET_WORD( TagOffset + 2 ) ; DataNum = GET_DWORD( TagOffset + 4 ) ; if( Type >= TYPE_NUM || TypeSize[ Type ] == 0 ) { return -1 ; } DataSize = TypeSize[ Type ] * DataNum ; if( DataSize > 4 ) { DataOffset = GET_DWORD( TagOffset + 8 ) ; } else { DataOffset = TagOffset + 8 ; } for( i = 0 ; i < DataNum ; i ++ ) { switch( Type ) { case 1 : // BYTE (8bit unsigned integer) case 2 : // ASCII (NULLで終わる文字列) case 7 : // Undefined (8bit値) *( ( BYTE * )DataBuffer ) = ( BYTE )GET_BYTE( DataOffset ) ; DataBuffer ++ ; DataOffset ++ ; break ; case 3 : // SHORT (16bit unsigned integer) *( ( WORD * )DataBuffer ) = ( WORD )GET_WORD( DataOffset ) ; DataBuffer += 2 ; DataOffset += 2 ; break ; case 4 : // LONG (32bit unsigned integer) case 9 : // SLONG (32bit signed integer) *( ( DWORD * )DataBuffer ) = ( DWORD )GET_DWORD( DataOffset ) ; DataBuffer += 4 ; DataOffset += 4 ; break ; case 5 : // RATIONAL (2つのLONGの比; unsigned double) case 10 : // SRATIONAL (2つのSLONGの比; signed double) *( ( DWORD * )&DataBuffer[ 0 ] ) = ( DWORD )GET_DWORD( DataOffset + 0 ) ; *( ( DWORD * )&DataBuffer[ 4 ] ) = ( DWORD )GET_DWORD( DataOffset + 4 ) ; DataBuffer += 8 ; DataOffset += 8 ; break ; } } return 0 ; } // Exif の GPS の情報を取得する int GetExifGPSInfo( ExifGPSInfo *Info ) { DWORD number_of_tags ; DWORD firstoffset ; DWORD gpsoffset ; int i, j ; // データサイズが18バイト以下だったら情報が足りないので処理しない if( ExifSize < 18 ) return -1 ; // バイトオーダー判定 switch( GET_WORD( 0 ) ) { case 0x4949 : is_motorola = FALSE ; // リトルエンディアン break ; case 0x4d4d : is_motorola = TRUE ; // ビッグエンディアン break ; default : return -1 ; } // TAGマーカーチェック if( GET_WORD( 2 ) != 0x002a ) { return -1 ; } // 最初の IFD へのオフセットを取得 firstoffset = GET_DWORD( 4 ) ; if( firstoffset > 0xffff || firstoffset > ExifSize - 8 ) { return -1 ; } // ディレクトリエントリの数を取得 number_of_tags = GET_WORD( firstoffset ) ; if( number_of_tags == 0 ) { return -1 ; } firstoffset += 2 ; // GPS IFD へのポインタタグを探す firstoffset = SearchTag( firstoffset, 0x8825, number_of_tags ) ; if( firstoffset == 0xffffffff ) { return -1 ; } // GPS IFD へのオフセットを取得 gpsoffset = GET_DWORD( firstoffset + 8 ) ; if( gpsoffset > 0xffff || gpsoffset > ExifSize - 8 ) { return -1 ; } // GPS IFD のディレクトリエントリの数を取得 number_of_tags = GET_WORD( gpsoffset ) ; if( number_of_tags == 0 ) { return -1 ; } gpsoffset += 2 ; // GPSの情報を初期化する Info->GPSLatitudeRef[ 0 ] = '\0' ; Info->GPSLongitudeRef[ 0 ] = '\0' ; for( i = 0 ; i < 3 ; i ++ ) { for( j = 0 ; j < 2 ; j ++ ) { Info->GPSLatitude[ i ][ j ] = -1 ; Info->GPSLongitude[ i ][ j ] = -1 ; } } Info->GPSAltitudeRef[ 0 ] = -1 ; Info->GPSAltitudeRef[ 1 ] = -1 ; Info->GPSAltitude[ 0 ] = -1 ; Info->GPSAltitude[ 1 ] = -1 ; // GPSの情報を取得する GetTagInfo( gpsoffset, number_of_tags, 1, ( BYTE * )Info->GPSLatitudeRef ) ; GetTagInfo( gpsoffset, number_of_tags, 2, ( BYTE * )Info->GPSLatitude ) ; GetTagInfo( gpsoffset, number_of_tags, 3, ( BYTE * )Info->GPSLongitudeRef ) ; GetTagInfo( gpsoffset, number_of_tags, 4, ( BYTE * )Info->GPSLongitude ) ; GetTagInfo( gpsoffset, number_of_tags, 5, ( BYTE * )Info->GPSAltitudeRef ) ; GetTagInfo( gpsoffset, number_of_tags, 6, ( BYTE * )Info->GPSAltitude ) ; return 0 ; } int WINAPI WinMain( HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nCmdShow ) { ExifGPSInfo GPSInfo ; ChangeWindowMode( TRUE ) ; // DXライブラリの初期化 if( DxLib_Init() < 0 ) { // エラーが発生したら直ちに終了 return -1 ; } SetDrawScreen( DX_SCREEN_BACK ) ; // Exif情報を読み込み ExifSize = ( DWORD )ReadJpegExif( "TestJpeg.jpg", Exif, sizeof( Exif ) ) ; // Exif情報からGPSの情報を取得する if( GetExifGPSInfo( &GPSInfo ) < 0 ) { DrawString( 0, 0, "GPSの情報がありません", GetColor( 255,255,255 ) ) ; } else { DrawFormatString( 0, 16 * 0, GetColor( 255,255,255 ), "緯度(N/S) : %s", GPSInfo.GPSLatitudeRef ) ; DrawFormatString( 0, 16 * 1, GetColor( 255,255,255 ), "緯度(数値) : %d° %d %.3f [DMS]", GPSInfo.GPSLatitude[ 0 ][ 0 ] / GPSInfo.GPSLatitude[ 0 ][ 1 ], GPSInfo.GPSLatitude[ 1 ][ 0 ] / GPSInfo.GPSLatitude[ 1 ][ 1 ], ( double )GPSInfo.GPSLatitude[ 2 ][ 0 ] / GPSInfo.GPSLatitude[ 2 ][ 1 ] ) ; DrawFormatString( 0, 16 * 2, GetColor( 255,255,255 ), "経度(E/W) : %s", GPSInfo.GPSLongitudeRef ) ; DrawFormatString( 0, 16 * 3, GetColor( 255,255,255 ), "経度(数値) : %d° %d %.3f [DMS]", GPSInfo.GPSLongitude[ 0 ][ 0 ] / GPSInfo.GPSLongitude[ 0 ][ 1 ], GPSInfo.GPSLongitude[ 1 ][ 0 ] / GPSInfo.GPSLongitude[ 1 ][ 1 ], ( double )GPSInfo.GPSLongitude[ 2 ][ 0 ] / GPSInfo.GPSLongitude[ 2 ][ 1 ] ) ; DrawFormatString( 0, 16 * 4, GetColor( 255,255,255 ), "高度基準 : %d", GPSInfo.GPSAltitudeRef[ 0 ] ) ; DrawFormatString( 0, 16 * 5, GetColor( 255,255,255 ), "高度 : %d/%d メートル", GPSInfo.GPSAltitude[ 0 ], GPSInfo.GPSAltitude[ 1 ] ) ; } ScreenFlip() ; WaitKey() ; DxLib_End() ; // ソフトの終了 return 0 ; } WinMain 関数の ReadJpegExif を使用している箇所のJPEGファイル名をお手元の GPS 情報が含まれる JPEGファイルにしていただければ、実行すると画面に緯度、経度、高度が表示されると思います
メンテ
Re: Exif情報の取得方法 ( No.4 )
名前:KKK 日時:2016/11/15 09:54

ご返信ありがとうございます。 早速試してみたところ、ちゃんとGPS情報を読み取れることを確認しました。 追加で質問してしまって申し訳ないのですが、これに加えて画像の撮影日時(年、月、日)も読み取るようにはできませんか?
メンテ
Re: Exif情報の取得方法 ( No.5 )
名前:管理人 日時:2016/11/16 01:22

はい、できます サンプルプログラムを撮影日時も表示するように変更してみました 因みに日時の情報はただの19文字( + 終端文字 )の文字列なので、 数値として扱う場合は文字列解析が必要です #include "DxLib.h" BYTE Exif[ 0xffff ] ; DWORD ExifSize ; int is_motorola ; struct ExifGPSInfo { char GPSLatitudeRef[ 2 ] ; // 緯度の南北( N or S ) int GPSLatitude[ 3 ][ 2 ] ; // 緯度(度、分、秒) char GPSLongitudeRef[ 2 ] ; // 経度の東西( E or W ) int GPSLongitude[ 3 ][ 2 ] ; // 経度(度、分、秒) char GPSAltitudeRef[ 2 ] ; // 高度の基準 int GPSAltitude[ 2 ] ; // 高度(m) char Date[ 20 ] ; // 日時( これだけは GPS IFD の情報ではなく Exif IFD の情報です ) } ; #define GET_BYTE( off ) Exif[ (off) + 0 + 6 ] #define GET_WORD( off ) \ ( is_motorola ? \ ( ( Exif[ (off) + 0 + 6 ] << 8 ) | ( Exif[ (off) + 1 + 6 ] ) ) :\ ( ( Exif[ (off) + 1 + 6 ] << 8 ) | ( Exif[ (off) + 0 + 6 ] ) ) ) #define GET_DWORD( off ) \ ( is_motorola ? \ ( ( Exif[ (off) + 0 + 6 ] << 24 ) | ( Exif[ (off) + 1 + 6 ] << 16 ) | ( Exif[ (off) + 2 + 6 ] << 8 ) | ( Exif[ (off) + 3 + 6 ] ) ) :\ ( ( Exif[ (off) + 3 + 6 ] << 24 ) | ( Exif[ (off) + 2 + 6 ] << 16 ) | ( Exif[ (off) + 1 + 6 ] << 8 ) | ( Exif[ (off) + 0 + 6 ] ) ) ) #define TYPE_NUM (11) DWORD TypeSize[ TYPE_NUM ] = { 0, // 0 : 未定義 1, // 1 : BYTE (8bit unsigned integer) 1, // 2 : ASCII (NULLで終わる文字列) 2, // 3 : SHORT (16bit unsigned integer) 4, // 4 : LONG (32bit unsigned integer) 8, // 5 : RATIONAL (2つのLONGの比; unsigned double) 0, // 6 : 未定義 1, // 7 : Undefined (8bit値) 0, // 8 : 未定義 4, // 9 : SLONG (32bit signed integer) 8, // 10 : SRATIONAL (2つのSLONGの比; signed double) } ; // 指定番号のタグを探す DWORD SearchTag( DWORD Offset, DWORD NumberOfTags, WORD Tag ) { for(;;) { // 残りデータのサイズをチェック if( Offset > ExifSize - 18 ) { return 0xffffffff ; } // GPS IFD へのポインタタグだったらループから抜ける if( GET_WORD( Offset ) == Tag ) { return Offset ; } // ディレクトリエントリを全て調べてなかったら終了 NumberOfTags-- ; if( NumberOfTags == 0 ) { return 0xffffffff ; } // 調べるオフセットを進める Offset += 12 ; } } // タグの情報を取得する int GetTagInfo( DWORD Offset, DWORD NumberOfTags, WORD Tag, BYTE *DataBuffer ) { DWORD TagOffset ; WORD Type ; DWORD DataNum ; DWORD DataSize ; DWORD DataOffset ; DWORD i ; TagOffset = SearchTag( Offset, NumberOfTags, Tag ) ; if( TagOffset == 0xffffffff ) { return -1 ; } Type = GET_WORD( TagOffset + 2 ) ; DataNum = GET_DWORD( TagOffset + 4 ) ; if( Type >= TYPE_NUM || TypeSize[ Type ] == 0 ) { return -1 ; } DataSize = TypeSize[ Type ] * DataNum ; if( DataSize > 4 ) { DataOffset = GET_DWORD( TagOffset + 8 ) ; } else { DataOffset = TagOffset + 8 ; } for( i = 0 ; i < DataNum ; i ++ ) { switch( Type ) { case 1 : // BYTE (8bit unsigned integer) case 2 : // ASCII (NULLで終わる文字列) case 7 : // Undefined (8bit値) *( ( BYTE * )DataBuffer ) = ( BYTE )GET_BYTE( DataOffset ) ; DataBuffer ++ ; DataOffset ++ ; break ; case 3 : // SHORT (16bit unsigned integer) *( ( WORD * )DataBuffer ) = ( WORD )GET_WORD( DataOffset ) ; DataBuffer += 2 ; DataOffset += 2 ; break ; case 4 : // LONG (32bit unsigned integer) case 9 : // SLONG (32bit signed integer) *( ( DWORD * )DataBuffer ) = ( DWORD )GET_DWORD( DataOffset ) ; DataBuffer += 4 ; DataOffset += 4 ; break ; case 5 : // RATIONAL (2つのLONGの比; unsigned double) case 10 : // SRATIONAL (2つのSLONGの比; signed double) *( ( DWORD * )&DataBuffer[ 0 ] ) = ( DWORD )GET_DWORD( DataOffset + 0 ) ; *( ( DWORD * )&DataBuffer[ 4 ] ) = ( DWORD )GET_DWORD( DataOffset + 4 ) ; DataBuffer += 8 ; DataOffset += 8 ; break ; } } return 0 ; } // IFD の情報を取得する DWORD GetIFDInfo( DWORD Offset, DWORD NumberOfTags, WORD Tag, DWORD *IFDNumberOfTags ) { DWORD result_offset ; // 指定の IFD へのポインタタグを探す result_offset = SearchTag( Offset, NumberOfTags, Tag ) ; if( result_offset == 0xffffffff ) { return 0xffffffff ; } // IFD へのオフセットを取得 result_offset = GET_DWORD( result_offset + 8 ) ; if( result_offset > 0xffff || result_offset > ExifSize - 8 ) { return 0xffffffff ; } // IFD のディレクトリエントリの数を取得 *IFDNumberOfTags = GET_WORD( result_offset ) ; if( *IFDNumberOfTags == 0 ) { return 0xffffffff ; } result_offset += 2 ; return result_offset ; } // Exif の GPS の情報を取得する int GetExifGPSInfo( ExifGPSInfo *Info ) { DWORD first_offset ; DWORD first_number_of_tags ; DWORD exif_offset ; DWORD exif_number_of_tags ; DWORD gps_offset ; DWORD gps_number_of_tags ; int i, j ; // 情報を初期化する Info->GPSLatitudeRef[ 0 ] = '\0' ; Info->GPSLongitudeRef[ 0 ] = '\0' ; for( i = 0 ; i < 3 ; i ++ ) { for( j = 0 ; j < 2 ; j ++ ) { Info->GPSLatitude[ i ][ j ] = -1 ; Info->GPSLongitude[ i ][ j ] = -1 ; } } Info->GPSAltitudeRef[ 0 ] = -1 ; Info->GPSAltitudeRef[ 1 ] = -1 ; Info->GPSAltitude[ 0 ] = -1 ; Info->GPSAltitude[ 1 ] = -1 ; strcpy( Info->Date, "----:--:-- --:--:--" ) ; // データサイズが18バイト以下だったら情報が足りないので処理しない if( ExifSize < 18 ) return -1 ; // バイトオーダー判定 switch( GET_WORD( 0 ) ) { case 0x4949 : is_motorola = FALSE ; // リトルエンディアン break ; case 0x4d4d : is_motorola = TRUE ; // ビッグエンディアン break ; default : return -1 ; } // TAGマーカーチェック if( GET_WORD( 2 ) != 0x002a ) { return -1 ; } // 最初の IFD へのオフセットを取得 first_offset = GET_DWORD( 4 ) ; if( first_offset > 0xffff || first_offset > ExifSize - 8 ) { return -1 ; } // ディレクトリエントリの数を取得 first_number_of_tags = GET_WORD( first_offset ) ; if( first_number_of_tags == 0 ) { return -1 ; } first_offset += 2 ; // Exif IFD の情報を取得する exif_offset = GetIFDInfo( first_offset, first_number_of_tags, 0x8769, &exif_number_of_tags ) ; if( exif_offset != 0xffffffff ) { // 日時を取得する GetTagInfo( exif_offset, exif_number_of_tags, 0x9003, ( BYTE * )Info->Date ) ; } // GPS IFD の情報を取得する gps_offset = GetIFDInfo( first_offset, first_number_of_tags, 0x8825, &gps_number_of_tags ) ; if( gps_offset != 0xffffffff ) { // GPSの情報を取得する GetTagInfo( gps_offset, gps_number_of_tags, 1, ( BYTE * )Info->GPSLatitudeRef ) ; GetTagInfo( gps_offset, gps_number_of_tags, 2, ( BYTE * )Info->GPSLatitude ) ; GetTagInfo( gps_offset, gps_number_of_tags, 3, ( BYTE * )Info->GPSLongitudeRef ) ; GetTagInfo( gps_offset, gps_number_of_tags, 4, ( BYTE * )Info->GPSLongitude ) ; GetTagInfo( gps_offset, gps_number_of_tags, 5, ( BYTE * )Info->GPSAltitudeRef ) ; GetTagInfo( gps_offset, gps_number_of_tags, 6, ( BYTE * )Info->GPSAltitude ) ; return 0 ; } return -1 ; } int WINAPI WinMain( HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nCmdShow ) { ExifGPSInfo GPSInfo ; ChangeWindowMode( TRUE ) ; // DXライブラリの初期化 if( DxLib_Init() < 0 ) { // エラーが発生したら直ちに終了 return -1 ; } SetDrawScreen( DX_SCREEN_BACK ) ; ExifSize = ( DWORD )ReadJpegExif( "TestJpeg.jpg", Exif, sizeof( Exif ) ) ; if( GetExifGPSInfo( &GPSInfo ) < 0 ) { DrawString( 0, 0, "GPSの情報がありません", GetColor( 255,255,255 ) ) ; } else { DrawFormatString( 0, 16 * 0, GetColor( 255,255,255 ), "緯度(N/S) : %s", GPSInfo.GPSLatitudeRef ) ; DrawFormatString( 0, 16 * 1, GetColor( 255,255,255 ), "緯度(数値) : %d° %d %.3f [DMS]", GPSInfo.GPSLatitude[ 0 ][ 0 ] / GPSInfo.GPSLatitude[ 0 ][ 1 ], GPSInfo.GPSLatitude[ 1 ][ 0 ] / GPSInfo.GPSLatitude[ 1 ][ 1 ], ( double )GPSInfo.GPSLatitude[ 2 ][ 0 ] / GPSInfo.GPSLatitude[ 2 ][ 1 ] ) ; DrawFormatString( 0, 16 * 2, GetColor( 255,255,255 ), "経度(E/W) : %s", GPSInfo.GPSLongitudeRef ) ; DrawFormatString( 0, 16 * 3, GetColor( 255,255,255 ), "経度(数値) : %d° %d %.3f [DMS]", GPSInfo.GPSLongitude[ 0 ][ 0 ] / GPSInfo.GPSLongitude[ 0 ][ 1 ], GPSInfo.GPSLongitude[ 1 ][ 0 ] / GPSInfo.GPSLongitude[ 1 ][ 1 ], ( double )GPSInfo.GPSLongitude[ 2 ][ 0 ] / GPSInfo.GPSLongitude[ 2 ][ 1 ] ) ; DrawFormatString( 0, 16 * 4, GetColor( 255,255,255 ), "高度基準 : %d", GPSInfo.GPSAltitudeRef[ 0 ] ) ; DrawFormatString( 0, 16 * 5, GetColor( 255,255,255 ), "高度 : %d/%d メートル", GPSInfo.GPSAltitude[ 0 ], GPSInfo.GPSAltitude[ 1 ] ) ; DrawFormatString( 0, 16 * 6, GetColor( 255,255,255 ), "撮影日時 : %s", GPSInfo.Date ) ; } ScreenFlip() ; WaitKey() ; DxLib_End() ; // ソフトの終了 return 0 ; }
メンテ
Re: Exif情報の取得方法 ( No.6 )
名前:KKK(解決) 日時:2016/11/16 13:13

ご返答ありがとうございました。 おかげで目的のプログラムの計算に使えそうです。文字列解析は自分でやってみようと思います。 ご丁寧に対応してくださりありがとうございました。
メンテ
Re: Exif情報の取得方法 ( No.7 )
名前:KKK 日時:2017/01/19 18:15

解決と言ったのにもかかわらず、また質問してしまってすみません。 前回の質問で、Exifを読み取るためのプログラムについて教えてもらったのですが、さらに他のことをやろうとしたときに Exif読み取りの原理・方法についてしっかりと知っておく必要があると思い、このプログラムの内容を理解しようとしました。 しかし、プログラム経験の浅い私にとってはわからない部分が多く、Exifの構造について調べたのですがそれでもよくわかりません。 Exifの規格書を見ると、タグの番号ごとに所定の情報が設定されているのはわかります。そうすると、あるタグの情報を参照したいときは、 その番号をたどればいいのですか? このプログラムに関して、各処理がどんなことをやっていているのか、具体的にどういう手順でGPS情報などを参照しているのか説明してもらえないでしょうか? 無理を言って本当に申し訳ないのですが、どうかお願いします。
メンテ
Re: Exif情報の取得方法 ( No.8 )
名前:yumetodo 日時:2017/01/19 23:39

To 管理人さん ちょっと便乗でお願いなのですが、現状ReadJpegExif関数は予め書き込み先を大きさ決め打ちで確保する必要があります。 これだと使いにくいので、DxLib側で動的確保して呼び出し側でDxFreeを呼びだすようにしてもらえないでしょうか・・・。 上のサンプルだと63KBも決め打ちで確保していますがどうかと思いますし・・・。 つまり BYTE* ReadJpegExifWithAlloc(const TCHAR *JpegFilePath, size_t* pExifBufferSize ); のような関数ですね。
メンテ
Re: Exif情報の取得方法 ( No.9 )
名前:yumetodo 日時:2017/01/20 00:47

To KKK >具体的にどういう手順でGPS情報などを参照しているのか 書こうと思ったらどうやっても弾かれるのでpastebinにて http ://pastebin.com/cCzZ9GZj
メンテ
Re: Exif情報の取得方法 ( No.10 )
名前:管理人 日時:2017/01/20 01:34

yumetodoさんが No.9 のお書き込みで Exif の理解についてのご説明をされていますが 私も参考にさせていただいたサイトのご紹介などを… > そうすると、あるタグの情報を参照したいときは、その番号をたどればいいのですか? はい ただ、Exif の中に含まれるタグの集まり( IFD )は一つではないので、例えば GPS の情報を 取得する場合は First IFD の中に含まれる GPS Info IFD Pointer タグから GPS Info IFD が 格納されているアドレスを取得して、その後 GPS Info IFD の中の GPSLatitude タグなどから GPS の位置情報などを取得する、といったことをする必要があります Exif の構造についてはこちらのページを参考にさせていただきましたので、よろしければご覧ください <DSAS開発者の部屋  Exif データにアクセスするコードを自作してみる> http://dsas.blog.klab.org/archives/52123322.html あと、タグ番号の一覧はこちらのページを参考にさせていただきました <Kenshi's Page  Exifファイルフォーマット> http://www2.airnet.ne.jp/~kenshi/exif.html Exif の詳しい構造はこちらのページを参考にさせていただきました ( ただ、こちらでは GPS IFD についての解説はありません ) <dinop.com> http://www.dinop.com/vc/exif01.html <Exifファイル(1回目) 〜 ファイル概要 〜> http://www.dinop.com/vc/exif02.html <Exifファイル(2回目) 〜 情報取出 〜> http://www.dinop.com/vc/exif03.html <Exifファイル(3回目) 〜 情報種類 〜> http://www.dinop.com/vc/exif04.html <Exifファイル(4回目) 〜 Exif IFD解説 〜> > このプログラムに関して、各処理がどんなことをやっていているのか、具体的にどういう手順でGPS情報などを参照しているのか説明してもらえないでしょうか? 解説しようとするとご紹介させていただいたサイトにある解説と 同じくらいの文章量になってしまうので、申し訳ありませんがまず上記の サイトをご覧になっていただいて、Exif の構造を理解してみてください 構造が理解できれば No.5 のプログラムの各箇所が何をしているのかも 理解していただけるかと思います m(_ _;m > yumetodoさん > これだと使いにくいので、DxLib側で動的確保して呼び出し側でDxFreeを呼びだすようにしてもらえないでしょうか・・・。 Jpeg に含まれる Exif は Jpegの規格上 0xffff を超えるサイズになることは ないそうですので、バッファサイズは 0xffff 決め打ちで問題ありません ( libjpeg の Exif 読み込みサンプルプログラムの transupp.c でも 0xffff 決め打ちです ) きちんとしたプログラムを書かれたい方は ExifBuffer に NULL を渡して戻り値の サイズ分のメモリを確保していただければと思います…
メンテ
Re: Exif情報の取得方法 ( No.11 )
名前:KKK 日時:2017/01/20 20:20

yumetodo様が仰っていた"libjpgのjpeg_read_header関数を呼び出す"というのは、 No.3の管理人様の書き込みであったReadJpegExif関数で行なっているのですか? 管理人様の説明では、この関数は"Exifのバイナリを取得"とあるのですが、この行為というのは 「TIFFヘッダ及び全IFDを2進数として読み込んでいる」という解釈で合っているのでしょうか? このReadJpegExif関数がどんな処理をしているのかがいまいちわからないので、 この関数の具体的な内容についても教えていただけませんか?
メンテ
Re: Exif情報の取得方法 ( No.12 )
名前:管理人 日時:2017/01/22 12:33

> yumetodo様が仰っていた"libjpgのjpeg_read_header関数を呼び出す"というのは、 > No.3の管理人様の書き込みであったReadJpegExif関数で行なっているのですか? はい、ReadJpegExif の内部で libjpeg の関数 jpeg_read_header を呼んでいます > このReadJpegExif関数がどんな処理をしているのかがいまいちわからないので、 > この関数の具体的な内容についても教えていただけませんか? ReadJpegExif 関数は引数 ExifBuffer で渡されたメモリアドレスの領域に Jpegファイルに 含まれている Exif情報を無加工でただコピーしています( 読み込みには libjpeg の関数を使用しています ) Exif情報には何も手を加えていませんので、ExifBffer が示すメモリ領域に格納されるデータに 関しては No.10 でご紹介させていただいたサイトで解説されている Exif の内部構造の情報を そのまま適用することができます( 最初の 2バイトでビッグエンディアンなのかリトルエンディアン なのか判断できる、次の 2バイトが 0x002a かどうかで Exif 情報であるか判断できる等 )
メンテ
Re: Exif情報の取得方法 ( No.13 )
名前:KKK(解決) 日時:2017/01/23 00:50

ご返信ありがとうございました。 だいぶわかってきたような気がします。もう少し勉強してlibjpgなどについてもわかるようになってから、 このプログラムの応用を考えたいと思います。 管理人様、yumetodo様、この度は本当にありがとうございました。
メンテ

Page: 1 |

題名
名前
コメント
パスワード (記事メンテ時に使用)

   クッキー保存