|
|
|
@ -3,15 +3,11 @@ package de.trac.spherical.parser;
|
|
|
|
|
import android.util.Log; |
|
|
|
|
|
|
|
|
|
import java.io.EOFException; |
|
|
|
|
import java.io.File; |
|
|
|
|
import java.io.FileInputStream; |
|
|
|
|
import java.io.IOException; |
|
|
|
|
import java.io.InputStream; |
|
|
|
|
import java.io.PushbackInputStream; |
|
|
|
|
import java.math.BigInteger; |
|
|
|
|
import java.text.ParseException; |
|
|
|
|
import java.text.SimpleDateFormat; |
|
|
|
|
import java.util.ArrayList; |
|
|
|
|
import java.util.Arrays; |
|
|
|
|
import java.util.Date; |
|
|
|
|
import java.util.Locale; |
|
|
|
@ -37,7 +33,7 @@ import static de.trac.spherical.parser.PhotoSphereMetadata.POSE_ROLL_DEGREES;
|
|
|
|
|
import static de.trac.spherical.parser.PhotoSphereMetadata.PROJECTION_TYPE; |
|
|
|
|
import static de.trac.spherical.parser.PhotoSphereMetadata.SOURCE_PHOTOS_COUNT; |
|
|
|
|
import static de.trac.spherical.parser.PhotoSphereMetadata.STITCHING_SOFTWARE; |
|
|
|
|
import static de.trac.spherical.parser.PhotoSphereMetadata.TYPE; |
|
|
|
|
import static de.trac.spherical.parser.PhotoSphereMetadata.ProjectionType; |
|
|
|
|
import static de.trac.spherical.parser.PhotoSphereMetadata.USE_PANORAMA_VIEWER; |
|
|
|
|
|
|
|
|
|
/** |
|
|
|
@ -45,7 +41,7 @@ import static de.trac.spherical.parser.PhotoSphereMetadata.USE_PANORAMA_VIEWER;
|
|
|
|
|
*/ |
|
|
|
|
public class SphereParser { |
|
|
|
|
|
|
|
|
|
public static final String TAG = "SphereParser"; |
|
|
|
|
private static final String TAG = "PhoSphePars"; |
|
|
|
|
|
|
|
|
|
private static final SimpleDateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd'T'hh:mm:ss.SSS'Z'", Locale.US); |
|
|
|
|
|
|
|
|
@ -56,23 +52,23 @@ public class SphereParser {
|
|
|
|
|
* 3 E1 |
|
|
|
|
* 4 Length EXIF (n) |
|
|
|
|
* 5 Length EXIF (n) |
|
|
|
|
* 6 <exif> |
|
|
|
|
* 6 <exif> (length n-2) |
|
|
|
|
* n+4 </exif> |
|
|
|
|
* n+5 FF |
|
|
|
|
* n+6 E1 |
|
|
|
|
* n+7 Length XML (m) |
|
|
|
|
* n+7 Length XML (m) |
|
|
|
|
* n+8 <xml> |
|
|
|
|
* n+8 <xml> (length m-2) |
|
|
|
|
* n+8+m</xml> |
|
|
|
|
* n+5 <xml> |
|
|
|
|
* ? </xml> |
|
|
|
|
*/ |
|
|
|
|
|
|
|
|
|
public static final byte[] FFE1 = new byte[] { |
|
|
|
|
private static final byte[] FFE1 = new byte[] { |
|
|
|
|
(byte) 0xFF, (byte) 0xE1 |
|
|
|
|
}; |
|
|
|
|
|
|
|
|
|
public static final byte[] FFD8FFE1 = new byte[] { |
|
|
|
|
private static final byte[] FFD8FFE1 = new byte[] { |
|
|
|
|
(byte) 0xFF, (byte) 0xD8, (byte) 0xFF, (byte) 0xE1 |
|
|
|
|
}; |
|
|
|
|
|
|
|
|
@ -86,7 +82,8 @@ public class SphereParser {
|
|
|
|
|
//HEADER
|
|
|
|
|
byte[] r = new byte[FFD8FFE1.length]; |
|
|
|
|
int i = inputStream.read(r); |
|
|
|
|
if (i != FFD8FFE1.length || !Arrays.equals(FFD8FFE1, r)) { |
|
|
|
|
throwIfUnexpectedEOF(i, r.length); |
|
|
|
|
if (!Arrays.equals(FFD8FFE1, r)) { |
|
|
|
|
Log.d(TAG, "Unexpected Image header: " + hex(r) + " (" + hex(FFD8FFE1) + " expected)"); |
|
|
|
|
return null; |
|
|
|
|
} |
|
|
|
@ -94,18 +91,18 @@ public class SphereParser {
|
|
|
|
|
//EXIF Length
|
|
|
|
|
r = new byte[2]; |
|
|
|
|
i = inputStream.read(r); |
|
|
|
|
if (i != 2) { |
|
|
|
|
throw new EOFException("Unexpected EOF!"); |
|
|
|
|
} |
|
|
|
|
throwIfUnexpectedEOF(i, r.length); |
|
|
|
|
int exifLen = integer(r); |
|
|
|
|
|
|
|
|
|
//Skip EXIF header
|
|
|
|
|
r = new byte[exifLen - 2]; |
|
|
|
|
i = inputStream.read(r); |
|
|
|
|
throwIfUnexpectedEOF(i, r.length); |
|
|
|
|
|
|
|
|
|
//XML Header
|
|
|
|
|
r = new byte[2]; |
|
|
|
|
i = inputStream.read(r); |
|
|
|
|
throwIfUnexpectedEOF(i, r.length); |
|
|
|
|
if (!Arrays.equals(FFE1, r)) { |
|
|
|
|
Log.d(TAG, "Image does not contain XML data."); |
|
|
|
|
return null; |
|
|
|
@ -113,16 +110,12 @@ public class SphereParser {
|
|
|
|
|
|
|
|
|
|
r = new byte[2]; |
|
|
|
|
i = inputStream.read(r); |
|
|
|
|
if (i != 2) { |
|
|
|
|
throw new EOFException("Unexpected EOF!"); |
|
|
|
|
} |
|
|
|
|
throwIfUnexpectedEOF(i, r.length); |
|
|
|
|
int xmlLen = integer(r); |
|
|
|
|
|
|
|
|
|
byte[] xml = new byte[xmlLen - 2]; |
|
|
|
|
i = inputStream.read(xml); |
|
|
|
|
if (i != xml.length) { |
|
|
|
|
throw new EOFException("Unexpected EOF!"); |
|
|
|
|
} |
|
|
|
|
throwIfUnexpectedEOF(i, r.length); |
|
|
|
|
|
|
|
|
|
return new String(xml); |
|
|
|
|
} |
|
|
|
@ -130,9 +123,9 @@ public class SphereParser {
|
|
|
|
|
public static PhotoSphereMetadata parse(String xmp) { |
|
|
|
|
PhotoSphereMetadata meta = new PhotoSphereMetadata(); |
|
|
|
|
meta.setUsePanoramaViewer(parseBoolean(USE_PANORAMA_VIEWER, xmp, true)); |
|
|
|
|
meta.setCaptureSoftware(getStringValue(CAPTURE_SOFTWARE, xmp)); |
|
|
|
|
meta.setStitichingSoftware(getStringValue(STITCHING_SOFTWARE, xmp)); |
|
|
|
|
meta.setProjectionType(parseType(PROJECTION_TYPE, xmp, TYPE.equirectangular)); |
|
|
|
|
meta.setCaptureSoftware(parseString(CAPTURE_SOFTWARE, xmp)); |
|
|
|
|
meta.setStitchingSoftware(parseString(STITCHING_SOFTWARE, xmp)); |
|
|
|
|
meta.setProjectionType(parseType(PROJECTION_TYPE, xmp, ProjectionType.equirectangular)); |
|
|
|
|
meta.setPoseHeadingDegrees(parseFloat(POSE_HEADING_DEGREES, xmp, null)); |
|
|
|
|
meta.setPosePitchDegrees(parseFloat(POSE_PITCH_DEGREES, xmp, 0f)); |
|
|
|
|
meta.setPoseRollDegrees(parseFloat(POSE_ROLL_DEGREES, xmp, 0f)); |
|
|
|
@ -154,7 +147,13 @@ public class SphereParser {
|
|
|
|
|
return meta; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
public static String getStringValue(String key, String xmp) { |
|
|
|
|
private static void throwIfUnexpectedEOF(int actual, int expected) throws EOFException { |
|
|
|
|
if (actual != expected) { |
|
|
|
|
throw new EOFException("Unexpected EOF!"); |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
private static String parseString(String key, String xmp) { |
|
|
|
|
if (!xmp.contains(key)) { |
|
|
|
|
return null; |
|
|
|
|
} |
|
|
|
@ -165,13 +164,13 @@ public class SphereParser {
|
|
|
|
|
return value; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
public static Integer parseInteger(String key, String xmp, Integer defaultValue) { |
|
|
|
|
String value = getStringValue(key, xmp); |
|
|
|
|
private static Integer parseInteger(String key, String xmp, Integer defaultValue) { |
|
|
|
|
String value = parseString(key, xmp); |
|
|
|
|
return value == null ? defaultValue : Integer.parseInt(value); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
public static Float parseFloat(String key, String xmp, Float defaultValue) { |
|
|
|
|
String value = getStringValue(key, xmp); |
|
|
|
|
private static Float parseFloat(String key, String xmp, Float defaultValue) { |
|
|
|
|
String value = parseString(key, xmp); |
|
|
|
|
if (value == null) { |
|
|
|
|
return defaultValue; |
|
|
|
|
} else { |
|
|
|
@ -179,18 +178,18 @@ public class SphereParser {
|
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
public static Boolean parseBoolean(String key, String xmp, Boolean defaultValue) { |
|
|
|
|
String value = getStringValue(key, xmp); |
|
|
|
|
private static Boolean parseBoolean(String key, String xmp, Boolean defaultValue) { |
|
|
|
|
String value = parseString(key, xmp); |
|
|
|
|
return value == null ? defaultValue : Boolean.parseBoolean(value); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
public static TYPE parseType(String key, String xmp, TYPE defaultValue) { |
|
|
|
|
String value = getStringValue(key, xmp); |
|
|
|
|
return value == null ? defaultValue : TYPE.equirectangular; |
|
|
|
|
private static ProjectionType parseType(String key, String xmp, ProjectionType defaultValue) { |
|
|
|
|
String value = parseString(key, xmp); |
|
|
|
|
return value == null ? defaultValue : ProjectionType.equirectangular; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
public static Date parseDate(String key, String xmp, Date defaultValue) { |
|
|
|
|
String value = getStringValue(key, xmp); |
|
|
|
|
private static Date parseDate(String key, String xmp, Date defaultValue) { |
|
|
|
|
String value = parseString(key, xmp); |
|
|
|
|
try { |
|
|
|
|
return value == null ? defaultValue : dateFormat.parse(value); |
|
|
|
|
} catch (ParseException e) { |
|
|
|
@ -198,23 +197,6 @@ public class SphereParser {
|
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
public static void main(String[] args) throws IOException { |
|
|
|
|
File file = new File(args[0]); |
|
|
|
|
System.out.println(getXMLContent(new FileInputStream(file))); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
private static void unread(ArrayList<Byte> list, PushbackInputStream pb) throws IOException { |
|
|
|
|
for (int i = list.size() - 1; i >= 0; i--) { |
|
|
|
|
pb.unread(list.get(i)); |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
private static void append(ArrayList<Byte> list, byte[] array, int r) { |
|
|
|
|
for (int i = 0; i < r; i++) { |
|
|
|
|
list.add(array[i]); |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
private static String hex(byte[] b) { |
|
|
|
|
return new BigInteger(b).toString(16); |
|
|
|
|
} |
|
|
|
|