ホーム ] TIPS ウィンドウズ系 ] TIPS グラフィックス系 ] TIPS メルチメディア系 ] TIPS 理数系 ] TIPS 総覧 ]

上へ
M0101 JPGサイズの獲得
M0105 EXIFメーカノートを読む

VB.NET2005 TIPS /  マルチメディア系

M0105 EXIFメーカノートを読む

最終更新:2007/02/20  更新再掲

●解説

 標準のTag情報以外に、メーカ独自の情報が許されており、それがメーカノートと呼ばれるTagである。この部分は非公開なので、自分で試行錯誤して解析する必要があるが、重要な情報が含まれている場合がある。形式は任意なので、一般的には得ることはできなく、メーカ毎の対応が必要となる。ここでは、NIKON D70s のメーカノートの例を紹介する。

●原理

 メーカノートのTag値は&H927Cで、多分、必ず含まれている。PropertyItemクラスでは、Typeが7(任意)でその全てのデータがバイト配列でValueとして得られる。

●方法

 サイズと値(バイト値列)は標準コードで簡単に得られるので、後は、メーカ毎にそのバイト配列を解釈して行く。

 NIKON D70sでは、この部分もIFD形式となっており、独自のTagで構成されているが、IFDとして標準的に処理ができる。データの先頭18バイトはTiffヘッダになっており、ここに、ここのデータのバイトオーダを示すコード"II"または"MM"がある。従って、以降のポインタはこのコードの位置が基準になる。


メーカノートTag(h927C、図では、7C92)と、メーカノート部分(青矢印の先)
NIKONメーカノートは、インテル形式である。

●実例

 ここでは、L4002 EXIFInfoを利用した例である。

frgT は私製グリッドコントロール
濃緑部分が、EXIFInfoクラス

Imports System.IO
Imports ExifInfo.ExifInfo
Imports System.Drawing.Imaging

Dim BB(), B() As Byte
Dim RD() As Object
Dim MED As ExifInfo.Endian
Dim i, j, Cnt, DCnt As Integer
Dim pi As PropertyItem = bmp.GetPropertyItem(TagNo("メーカノート"))
BB = pi.Value
Cnt = pi.Len
If AsciiByteToString(BB, 0, 6) = "NIKON" Then             'NIKONのヘッダチェック
   Dim ED As String = AsciiByteToString(BB, 10, 2)        'バイトオーダを得る
   Select Case ED
      Case "II"
         MED = ExifInfo.Endian.II
      Case "MM"
         MED = ExifInfo.Endian.MM
      Case Else
         MsgBox("メーカノートが不正です。", MsgBoxStyle.Critical)
         Exit Sub
   End Select
   Dim IFDP As Integer = 10 + 8          'オフセットは固定でOK
   Dim IFDC As Integer = UInt16ByteToInteger(BB, IFDP, MED)   'IFDの個数
   Dim Tag, BC, BCnt As Integer
   Dim Type As ExifInfo.ValueType
   Dim L, V As Long
   frgT.BeginUpdate()
   frgT.SetGridConstruction(8, IFDC + 1, 2, 1)
   frgT.RowHeader(0) = HdrM
   For i = 0 To IFDC - 1
      frgT(0, i + 1) = i + 1
      Tag = UInt16ByteToInteger(BB, IFDP + 2 + 12 * i + 0, MED)    'NIKON独自のTag番号
      frgT(1, i + 1) = Tag
      frgT(2, i + 1) = Hex(Tag)
      Type = UInt16ByteToInteger(BB, IFDP + 2 + 12 * i + 2, MED)   'データ型
      frgT(3, i + 1) = CInt(Type)
      frgT(4, i + 1) = TypeName(Type)
      L = UInt32ByteToLong(BB, IFDP + 2 + 12 * i + 4, MED)           'データ数
      frgT(5, i + 1) = L
      BC = UnitByteCount(Type)
      BCnt = L * BC
      frgT(6, i + 1) = BCnt
      If BCnt > 4 Then '値はポインタ
         V = UInt32ByteToLong(BB, IFDP + 2 + 12 * i + 8, MED) + 10    'ポインタ算出
      Else
         V = IFDP + 2 + 12 * i + 8
      End If
      ReDim B(BCnt - 1)
      For j = 0 To BCnt - 1
         If BB.Length <= (V + j) Then Exit For         'NIKON バグ対策
         B(j) = BB(V + j)                                            'データをバイト配列にする
      Next
      ByteToRawData(Type, BCnt, B, MED, RD, DCnt)
     '以下は、表示用の文字列を生成しているコード
      Dim D As String
      Select Case Type
         Case ExifInfo.ValueType.Any, ExifInfo.ValueType.Ascii, ExifInfo.ValueType.SByte, ExifInfo.ValueType.Ubyte
            frgT(7, i + 1) = RD(0)
         Case ExifInfo.ValueType.Int16, ExifInfo.ValueType.Int32, ExifInfo.ValueType.UInt16, ExifInfo.ValueType.UInt32
            D = ""
            D = CLng(RD(0)).ToString
            For j = 1 To DCnt - 1
               D = D + ", " + CLng(RD(j)).ToString
            Next
            frgT(7, i + 1) = D
         Case ExifInfo.ValueType.Int32R, ExifInfo.ValueType.Uint32R
            D = ""
            D = CLng(RD(0)).ToString + "/" + CLng(RD(1)).ToString + "(" + CDbl(RD(0) / RD(1)).ToString + ")"
            For j = 1 To DCnt \ 2 - 1
               D = D + ", " + CLng(RD(2 * j)).ToString + "/" + CLng(RD(2 * j + 1)).ToString + "(" + CDbl(RD(2 * j) / RD(2 * j + 1)).ToString + ")"
            Next
            frgT(7, i + 1) = D
      End Select
   Next
   frgT.ColTextAlign(2) = FreeGrid.TextAlign.Right
   frgT.EndUpdate()
Else
   MsgBox("メーカノートが不正です。", MsgBoxStyle.Critical)
End If


上記コードで読んだメーカノート