UWSCでEXIF情報を読んでみる
前に、写真の撮影日時の秒単位がShell.Applicationでは取れない、というのがあった。
stuncloudさんが回答してくれた「Wia.ImageFile」がベストだけど、気が向いたのでバイナリーを読んでみた。
スクリプト
Binaryモジュールに依存しています。
UWSCでバイナリーファイルの読み書き - じゅんじゅんのきまぐれ
OPTION EXPLICIT CALL ..\lib\Binary DIM h = Binary.Open(INPUT("target jpeg file?")) IF h = Binary.INVALID_HANDLE OR !Binary.Exist(h) THEN EXITEXIT CONST BYTE_NUM = 256 // jpegファイルヘッダー確認 DIM buf = Binary.ReadArray(h, 2) IFB buf[0] = $ff AND buf[1] = $d8 THEN buf = Binary.ReadArray(h, 4) IFB buf[0] = $ff AND buf[1] = $e0 THEN buf = Binary.ReadArray(h, ConvNum(buf, 2, 2) - 2) buf = Binary.ReadArray(h, 4) ENDIF IFB buf[0] = $ff AND buf[1] = $e1 THEN DIM size = ConvNum(buf, 2, 2) // Exif確認 buf = Binary.ReadArray(h, 14) IFB buf[0] = $45 AND buf[1] = $78 AND buf[2] = $69 AND buf[3] = $66 AND buf[4] = 0 AND buf[5] = 0 THEN size = size - 6 DIM e = 0 IFB buf[6] = $4d AND buf[7] = buf[6] AND buf[8] = 0 AND buf[9] = $2a THEN // big endian e = 1 ELSEIF buf[6] = $49 AND buf[7] = buf[6] AND buf[8] = $2a AND buf[9] = 0 THEN // little endian e = -1 ELSE MSGBOX("invalid endian") ENDIF IFB e THEN DIM offset = ConvNum(buf, 10, 4, e) - 8 IF offset > 0 THEN buf = Binary.ReadArray(h, offset) offset = offset + 8 // TIFFヘッダーからのオフセットに補正 WHILE size > offset offset = ReadTag(h, e, offset) WEND ENDIF ELSE MSGBOX("not tiff") ENDIF ELSE MSGBOX("not exif") ENDIF ELSE MSGBOX("not jpeg") ENDIF Binary.Close(h) FUNCTION ReadTag(h, e, offset) DIM tagNum, i, tag, typ, num, val, nxt, buf buf = Binary.ReadArray(h, 2) tagNum = ConvNum(buf, 0, 2, e) PRINT offset + " " + tagNum num = 12 * tagNum + 4 buf = Binary.ReadArray(h, num) offset = offset + num + 2 FOR i = 0 TO tagNum - 1 tag = ConvNum(buf, 12 * i + 0, 2, e) typ = ConvNum(buf, 12 * i + 2, 2, e) num = ConvNum(buf, 12 * i + 4, 4, e) val = ConvNum(buf, 12 * i + 8, 4, e) offset = ReadData(h, e, typ, num, val, offset) IF offset = $FFFFFFFF THEN BREAK PRINT i + " " + tag + " " + typ + " " + num + " " + val IFB tag = 34665 AND i < tagNum - 1 THEN IFB val > offset THEN Binary.ReadArray(h, val - offset) offset = val ENDIF IFB val = offset THEN offset = ReadTag(h, e, offset) ELSE MSGBOX("シーケンシャルリード失敗 Exif") ENDIF ENDIF NEXT nxt = ConvNum(buf, 12 * tagNum, 4, e) RESULT = offset FEND FUNCTION ReadData(h, e, typ, num, var val, offset) RESULT = offset DIM r = 0, i, buf SELECT typ CASE 1 // BYTE IF num > 4 THEN r = 1 CASE 2 // ASCII IFB num > 4 THEN r = -1 ELSE buf = val val = "" FOR i = 0 TO num - 1 val = val + CHR(INT(buf / POWER($100, 4 - i - 1)) AND $FF) NEXT ENDIF CASE 3 // SHORT IF num > 2 THEN r = 2 CASE 4 // LONG IF num > 1 THEN r = 4 CASE 5 // RATIONAL(long*2) r = 8 CASE 7 // UNDEFINED(BYTE) IF num > 4 THEN r = 1 CASE 9 // SLONG IFB num > 1 THEN r = 4 ELSEIF val > $7fffffff THEN val = val - $100000000 ENDIF CASE 10 // SRATIONAL(slong*2) r = -8 DEFAULT MSGBOX("invalid tag type") RESULT = $FFFFFFFF SELEND IFB r THEN IFB RESULT < val THEN Binary.ReadArray(h, val - RESULT) RESULT = val ENDIF DIM toStr = (r = -1), sr = (r = -8) IF toStr THEN r = 1 IF sr THEN r = 8 IFB RESULT = val THEN val = Binary.ReadArray(h, num * r) RESULT = RESULT + num * r ELSE toStr = FALSE MSGBOX("シーケンシャルリード失敗") ENDIF IFB r = 8 THEN buf = ConvNum(val, 0, 4, e) IF sr AND buf > $7fffffff THEN buf = buf - $10000000 i = ConvNum(val, 4, 4, e) IF sr AND i > $7fffffff THEN i = i - $100000000 val = buf / i ENDIF IFB toStr THEN buf = val val = "" FOR i = 0 TO num - 1 val = val + CHR(buf[i]) NEXT ENDIF ENDIF FEND FUNCTION ConvNum(buf, offset, len, endian=1) RESULT = 0 DIM i FOR i = offset TO len + offset - 1 IF endian > 0 THEN RESULT = RESULT * BYTE_NUM + buf[i] ELSE RESULT = RESULT * BYTE_NUM + buf[len + offset * 2 - 1 - i] NEXT FEND
けんしのページ - Exifファイルフォーマット -
を見ながら適当に書きました。
番号の意味もそこらへんを見てください。