Edited at

Ricoh thetaのJPGから角度を取り出すコード(2018年版)


はじめに


  • THETA Vの静止画から角度情報を取得して画像を正しい向きにする(天頂補正)際に実施した内容(取得編)




作業方針


  • THETA Vの静止画には角度情報がxmpとして入っているためその情報を取得する


    • 以前の方法では、リコー固有ブロックのExif情報を取得していました



  • 必要な部分だけ取り出す


    • XMLパーサなどを使用せずに軽量化




コード


XmpReader.cs

using UnityEngine;

using System.Collections;
using System.IO;
using System;

public class XmpReader
{
public static void SerchAngle(string filePath)
{
BinaryReader br = new BinaryReader(new FileStream(filePath, FileMode.Open));
byte [] buf = br.ReadBytes((int)br.BaseStream.Length);
br.Close();
br = null;

float pitch = getPitch(buf);
float roll = getRoll(buf);

Debug.Log("filePath : " + filePath);
Debug.Log("pitch : " + pitch + ", roll : " + roll);
}

public static float getPitch(byte[] buf) {
string pitchStr = getXMLTagData(buf, "GPano:PosePitchDegrees");
float pitch = 0.0f;
if (pitchStr != "") {
pitch = float.Parse(pitchStr);
}
return pitch;
}

public static float getRoll(byte[] buf) {
string rollStr = getXMLTagData(buf, "GPano:PoseRollDegrees");
float roll = 0.0f;
if (rollStr != "") {
roll = float.Parse(rollStr);
}
return roll;
}

static string getXMLTagData(byte[] buf, string xmlTagName) {
string strStart = String.Format("<{0}>", xmlTagName);
byte[] byteStart = System.Text.Encoding.ASCII.GetBytes(strStart);
int xmp_start = findData(buf, byteStart);
if (xmp_start < 0) {
return "";
}
string strEnd = String.Format("</{0}>", xmlTagName);
byte[] byteEnd = System.Text.Encoding.ASCII.GetBytes(strEnd);
int xmp_end = findData(buf, byteEnd);
if (xmp_end < 0) {
return "";
}
xmp_end = xmp_end - strEnd.Length;

byte[] buf_get = new byte[255];
int copy_idx = 0;
for (int i=xmp_start;i<xmp_end; i++) {
buf_get[copy_idx] = buf[i];
copy_idx++;
}
string result = System.Text.Encoding.ASCII.GetString(buf_get);
return result;
}

static int findData(byte[] buf, byte[] pattern)
{
int max = buf.Length;
if (max > 64*1000) {
max = 64*1000;
}

for (int i = 0; i < max; i++) {
int iTemp = i;
for (int p = 0; p < pattern.Length ; p++, iTemp++) {
if (pattern[p] != buf[iTemp] || iTemp >= max) {
break;
}
if (p == pattern.Length - 1) {
return iTemp + 1;
}
}
}
return -1;
}
}



さいごに


  • この角度情報を実際に利用する方法はこちらに書きました



  • 他のアプリ(OculusGoのギャラリーなど)は、このXMPがあるためVR表示しますが天頂補正はしませんでした


参考資料