blob: 943a73febf1cba9ee9e812a13d0ef413cdb6253e [file] [log] [blame]
/*
* Copyright (C) 2013 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.android.camera2.its;
import android.graphics.Point;
import android.graphics.Rect;
import android.hardware.camera2.CameraCharacteristics;
import android.hardware.camera2.CameraDevice;
import android.hardware.camera2.CameraMetadata;
import android.hardware.camera2.CaptureResult;
import android.hardware.camera2.CaptureRequest;
import android.hardware.camera2.TotalCaptureResult;
import android.hardware.camera2.params.BlackLevelPattern;
import android.hardware.camera2.params.ColorSpaceTransform;
import android.hardware.camera2.params.Face;
import android.hardware.camera2.params.LensShadingMap;
import android.hardware.camera2.params.MeteringRectangle;
import android.hardware.camera2.params.RggbChannelVector;
import android.hardware.camera2.params.StreamConfigurationMap;
import android.hardware.camera2.params.TonemapCurve;
import android.location.Location;
import android.util.Log;
import android.util.Pair;
import android.util.Rational;
import android.util.Size;
import android.util.SizeF;
import android.util.Range;
import org.json.JSONArray;
import org.json.JSONObject;
import java.lang.reflect.Array;
import java.lang.reflect.Field;
import java.lang.reflect.GenericArrayType;
import java.lang.reflect.Modifier;
import java.lang.reflect.ParameterizedType;
import java.lang.reflect.Type;
import java.util.Arrays;
import java.util.LinkedList;
import java.util.List;
/**
* Class to deal with serializing and deserializing between JSON and Camera2 objects.
*/
public class ItsSerializer {
public static final String TAG = ItsSerializer.class.getSimpleName();
private static class MetadataEntry {
public MetadataEntry(String k, Object v) {
key = k;
value = v;
}
public String key;
public Object value;
}
@SuppressWarnings("unchecked")
private static Object serializeRational(Rational rat) throws org.json.JSONException {
JSONObject ratObj = new JSONObject();
ratObj.put("numerator", rat.getNumerator());
ratObj.put("denominator", rat.getDenominator());
return ratObj;
}
@SuppressWarnings("unchecked")
private static Object serializeSize(Size size) throws org.json.JSONException {
JSONObject sizeObj = new JSONObject();
sizeObj.put("width", size.getWidth());
sizeObj.put("height", size.getHeight());
return sizeObj;
}
@SuppressWarnings("unchecked")
private static Object serializeSizeF(SizeF size) throws org.json.JSONException {
JSONObject sizeObj = new JSONObject();
sizeObj.put("width", size.getWidth());
sizeObj.put("height", size.getHeight());
return sizeObj;
}
@SuppressWarnings("unchecked")
private static Object serializeRect(Rect rect) throws org.json.JSONException {
JSONObject rectObj = new JSONObject();
rectObj.put("left", rect.left);
rectObj.put("right", rect.right);
rectObj.put("top", rect.top);
rectObj.put("bottom", rect.bottom);
return rectObj;
}
private static Object serializePoint(Point point) throws org.json.JSONException {
JSONObject pointObj = new JSONObject();
pointObj.put("x", point.x);
pointObj.put("y", point.y);
return pointObj;
}
@SuppressWarnings("unchecked")
private static Object serializeFace(Face face)
throws org.json.JSONException {
JSONObject faceObj = new JSONObject();
faceObj.put("bounds", serializeRect(face.getBounds()));
faceObj.put("score", face.getScore());
faceObj.put("id", face.getId());
faceObj.put("leftEye", serializePoint(face.getLeftEyePosition()));
faceObj.put("rightEye", serializePoint(face.getRightEyePosition()));
faceObj.put("mouth", serializePoint(face.getMouthPosition()));
return faceObj;
}
@SuppressWarnings("unchecked")
private static Object serializeStreamConfigurationMap(
StreamConfigurationMap map)
throws org.json.JSONException {
// TODO: Serialize the rest of the StreamConfigurationMap fields.
JSONObject mapObj = new JSONObject();
JSONArray cfgArray = new JSONArray();
int fmts[] = map.getOutputFormats();
if (fmts != null) {
for (int fi = 0; fi < Array.getLength(fmts); fi++) {
Size sizes[] = map.getOutputSizes(fmts[fi]);
if (sizes != null) {
for (int si = 0; si < Array.getLength(sizes); si++) {
JSONObject obj = new JSONObject();
obj.put("format", fmts[fi]);
obj.put("width",sizes[si].getWidth());
obj.put("height", sizes[si].getHeight());
obj.put("input", false);
obj.put("minFrameDuration",
map.getOutputMinFrameDuration(fmts[fi],sizes[si]));
cfgArray.put(obj);
}
}
}
}
mapObj.put("availableStreamConfigurations", cfgArray);
return mapObj;
}
@SuppressWarnings("unchecked")
private static Object serializeMeteringRectangle(MeteringRectangle rect)
throws org.json.JSONException {
JSONObject rectObj = new JSONObject();
rectObj.put("x", rect.getX());
rectObj.put("y", rect.getY());
rectObj.put("width", rect.getWidth());
rectObj.put("height", rect.getHeight());
rectObj.put("weight", rect.getMeteringWeight());
return rectObj;
}
@SuppressWarnings("unchecked")
private static Object serializePair(Pair pair)
throws org.json.JSONException {
JSONArray pairObj = new JSONArray();
pairObj.put(pair.first);
pairObj.put(pair.second);
return pairObj;
}
@SuppressWarnings("unchecked")
private static Object serializeRange(Range range)
throws org.json.JSONException {
JSONArray rangeObj = new JSONArray();
rangeObj.put(range.getLower());
rangeObj.put(range.getUpper());
return rangeObj;
}
@SuppressWarnings("unchecked")
private static Object serializeColorSpaceTransform(ColorSpaceTransform xform)
throws org.json.JSONException {
JSONArray xformObj = new JSONArray();
for (int row = 0; row < 3; row++) {
for (int col = 0; col < 3; col++) {
xformObj.put(serializeRational(xform.getElement(col,row)));
}
}
return xformObj;
}
@SuppressWarnings("unchecked")
private static Object serializeTonemapCurve(TonemapCurve curve)
throws org.json.JSONException {
JSONObject curveObj = new JSONObject();
String names[] = {"red", "green", "blue"};
for (int ch = 0; ch < 3; ch++) {
JSONArray curveArr = new JSONArray();
int len = curve.getPointCount(ch);
for (int i = 0; i < len; i++) {
curveArr.put(curve.getPoint(ch,i).x);
curveArr.put(curve.getPoint(ch,i).y);
}
curveObj.put(names[ch], curveArr);
}
return curveObj;
}
@SuppressWarnings("unchecked")
private static Object serializeRggbChannelVector(RggbChannelVector vec)
throws org.json.JSONException {
JSONArray vecObj = new JSONArray();
vecObj.put(vec.getRed());
vecObj.put(vec.getGreenEven());
vecObj.put(vec.getGreenOdd());
vecObj.put(vec.getBlue());
return vecObj;
}
@SuppressWarnings("unchecked")
private static Object serializeBlackLevelPattern(BlackLevelPattern pat)
throws org.json.JSONException {
int patVals[] = new int[4];
pat.copyTo(patVals, 0);
JSONArray patObj = new JSONArray();
patObj.put(patVals[0]);
patObj.put(patVals[1]);
patObj.put(patVals[2]);
patObj.put(patVals[3]);
return patObj;
}
@SuppressWarnings("unchecked")
private static Object serializeLocation(Location loc)
throws org.json.JSONException {
return loc.toString();
}
@SuppressWarnings("unchecked")
private static Object serializeLensShadingMap(LensShadingMap map)
throws org.json.JSONException {
JSONArray mapObj = new JSONArray();
for (int row = 0; row < map.getRowCount(); row++) {
for (int col = 0; col < map.getColumnCount(); col++) {
for (int ch = 0; ch < 4; ch++) {
mapObj.put(map.getGainFactor(ch, col, row));
}
}
}
return mapObj;
}
private static String getKeyName(Object keyObj) throws ItsException {
if (keyObj.getClass() == CaptureResult.Key.class
|| keyObj.getClass() == TotalCaptureResult.class) {
return ((CaptureResult.Key)keyObj).getName();
} else if (keyObj.getClass() == CaptureRequest.Key.class) {
return ((CaptureRequest.Key)keyObj).getName();
} else if (keyObj.getClass() == CameraCharacteristics.Key.class) {
return ((CameraCharacteristics.Key)keyObj).getName();
}
throw new ItsException("Invalid key object");
}
private static Object getKeyValue(CameraMetadata md, Object keyObj) throws ItsException {
if (md.getClass() == CaptureResult.class || md.getClass() == TotalCaptureResult.class) {
return ((CaptureResult)md).get((CaptureResult.Key)keyObj);
} else if (md.getClass() == CaptureRequest.class) {
return ((CaptureRequest)md).get((CaptureRequest.Key)keyObj);
} else if (md.getClass() == CameraCharacteristics.class) {
return ((CameraCharacteristics)md).get((CameraCharacteristics.Key)keyObj);
}
throw new ItsException("Invalid key object");
}
@SuppressWarnings("unchecked")
private static MetadataEntry serializeEntry(Type keyType, Object keyObj, CameraMetadata md)
throws ItsException {
String keyName = getKeyName(keyObj);
try {
Object keyValue = getKeyValue(md, keyObj);
if (keyValue == null) {
return new MetadataEntry(keyName, JSONObject.NULL);
} else if (keyType == Float.class) {
// The JSON serializer doesn't handle floating point NaN or Inf.
if (((Float)keyValue).isInfinite() || ((Float)keyValue).isNaN()) {
Logt.w(TAG, "Inf/NaN floating point value serialized: " + keyName);
return null;
}
return new MetadataEntry(keyName, keyValue);
} else if (keyType == Integer.class || keyType == Long.class || keyType == Byte.class ||
keyType == Boolean.class || keyType == String.class) {
return new MetadataEntry(keyName, keyValue);
} else if (keyType == Rational.class) {
return new MetadataEntry(keyName, serializeRational((Rational)keyValue));
} else if (keyType == Size.class) {
return new MetadataEntry(keyName, serializeSize((Size)keyValue));
} else if (keyType == SizeF.class) {
return new MetadataEntry(keyName, serializeSizeF((SizeF)keyValue));
} else if (keyType == Rect.class) {
return new MetadataEntry(keyName, serializeRect((Rect)keyValue));
} else if (keyType == Face.class) {
return new MetadataEntry(keyName, serializeFace((Face)keyValue));
} else if (keyType == StreamConfigurationMap.class) {
return new MetadataEntry(keyName,
serializeStreamConfigurationMap((StreamConfigurationMap)keyValue));
} else if (keyType instanceof ParameterizedType &&
((ParameterizedType)keyType).getRawType() == Range.class) {
return new MetadataEntry(keyName, serializeRange((Range)keyValue));
} else if (keyType == ColorSpaceTransform.class) {
return new MetadataEntry(keyName,
serializeColorSpaceTransform((ColorSpaceTransform)keyValue));
} else if (keyType == MeteringRectangle.class) {
return new MetadataEntry(keyName,
serializeMeteringRectangle((MeteringRectangle)keyValue));
} else if (keyType == Location.class) {
return new MetadataEntry(keyName,
serializeLocation((Location)keyValue));
} else if (keyType == RggbChannelVector.class) {
return new MetadataEntry(keyName,
serializeRggbChannelVector((RggbChannelVector)keyValue));
} else if (keyType == BlackLevelPattern.class) {
return new MetadataEntry(keyName,
serializeBlackLevelPattern((BlackLevelPattern)keyValue));
} else if (keyType == TonemapCurve.class) {
return new MetadataEntry(keyName,
serializeTonemapCurve((TonemapCurve)keyValue));
} else if (keyType == Point.class) {
return new MetadataEntry(keyName,
serializePoint((Point)keyValue));
} else if (keyType == LensShadingMap.class) {
return new MetadataEntry(keyName,
serializeLensShadingMap((LensShadingMap)keyValue));
} else {
Logt.w(TAG, String.format("Serializing unsupported key type: " + keyType));
return null;
}
} catch (org.json.JSONException e) {
throw new ItsException("JSON error for key: " + keyName + ": ", e);
}
}
@SuppressWarnings("unchecked")
private static MetadataEntry serializeArrayEntry(Type keyType, Object keyObj, CameraMetadata md)
throws ItsException {
String keyName = getKeyName(keyObj);
try {
Object keyValue = getKeyValue(md, keyObj);
if (keyValue == null) {
return new MetadataEntry(keyName, JSONObject.NULL);
}
int arrayLen = Array.getLength(keyValue);
Type elmtType = ((GenericArrayType)keyType).getGenericComponentType();
if (elmtType == int.class || elmtType == float.class || elmtType == byte.class ||
elmtType == long.class || elmtType == double.class || elmtType == boolean.class) {
return new MetadataEntry(keyName, new JSONArray(keyValue));
} else if (elmtType == Rational.class) {
JSONArray jsonArray = new JSONArray();
for (int i = 0; i < arrayLen; i++) {
jsonArray.put(serializeRational((Rational)Array.get(keyValue,i)));
}
return new MetadataEntry(keyName, jsonArray);
} else if (elmtType == Size.class) {
JSONArray jsonArray = new JSONArray();
for (int i = 0; i < arrayLen; i++) {
jsonArray.put(serializeSize((Size)Array.get(keyValue,i)));
}
return new MetadataEntry(keyName, jsonArray);
} else if (elmtType == Rect.class) {
JSONArray jsonArray = new JSONArray();
for (int i = 0; i < arrayLen; i++) {
jsonArray.put(serializeRect((Rect)Array.get(keyValue,i)));
}
return new MetadataEntry(keyName, jsonArray);
} else if (elmtType == Face.class) {
JSONArray jsonArray = new JSONArray();
for (int i = 0; i < arrayLen; i++) {
jsonArray.put(serializeFace((Face)Array.get(keyValue, i)));
}
return new MetadataEntry(keyName, jsonArray);
} else if (elmtType == StreamConfigurationMap.class) {
JSONArray jsonArray = new JSONArray();
for (int i = 0; i < arrayLen; i++) {
jsonArray.put(serializeStreamConfigurationMap(
(StreamConfigurationMap)Array.get(keyValue,i)));
}
return new MetadataEntry(keyName, jsonArray);
} else if (elmtType instanceof ParameterizedType &&
((ParameterizedType)elmtType).getRawType() == Range.class) {
JSONArray jsonArray = new JSONArray();
for (int i = 0; i < arrayLen; i++) {
jsonArray.put(serializeRange((Range)Array.get(keyValue,i)));
}
return new MetadataEntry(keyName, jsonArray);
} else if (elmtType instanceof ParameterizedType &&
((ParameterizedType)elmtType).getRawType() == Pair.class) {
JSONArray jsonArray = new JSONArray();
for (int i = 0; i < arrayLen; i++) {
jsonArray.put(serializePair((Pair)Array.get(keyValue,i)));
}
return new MetadataEntry(keyName, jsonArray);
} else if (elmtType == MeteringRectangle.class) {
JSONArray jsonArray = new JSONArray();
for (int i = 0; i < arrayLen; i++) {
jsonArray.put(serializeMeteringRectangle(
(MeteringRectangle)Array.get(keyValue,i)));
}
return new MetadataEntry(keyName, jsonArray);
} else if (elmtType == Location.class) {
JSONArray jsonArray = new JSONArray();
for (int i = 0; i < arrayLen; i++) {
jsonArray.put(serializeLocation((Location)Array.get(keyValue,i)));
}
return new MetadataEntry(keyName, jsonArray);
} else if (elmtType == RggbChannelVector.class) {
JSONArray jsonArray = new JSONArray();
for (int i = 0; i < arrayLen; i++) {
jsonArray.put(serializeRggbChannelVector(
(RggbChannelVector)Array.get(keyValue,i)));
}
return new MetadataEntry(keyName, jsonArray);
} else if (elmtType == BlackLevelPattern.class) {
JSONArray jsonArray = new JSONArray();
for (int i = 0; i < arrayLen; i++) {
jsonArray.put(serializeBlackLevelPattern(
(BlackLevelPattern)Array.get(keyValue,i)));
}
return new MetadataEntry(keyName, jsonArray);
} else if (elmtType == Point.class) {
JSONArray jsonArray = new JSONArray();
for (int i = 0; i < arrayLen; i++) {
jsonArray.put(serializePoint((Point)Array.get(keyValue,i)));
}
return new MetadataEntry(keyName, jsonArray);
} else {
Logt.w(TAG, String.format("Serializing unsupported array type: " + elmtType));
return null;
}
} catch (org.json.JSONException e) {
throw new ItsException("JSON error for key: " + keyName + ": ", e);
}
}
@SuppressWarnings("unchecked")
public static JSONObject serialize(CameraMetadata md)
throws ItsException {
JSONObject jsonObj = new JSONObject();
Field[] allFields = md.getClass().getDeclaredFields();
if (md.getClass() == TotalCaptureResult.class) {
allFields = CaptureResult.class.getDeclaredFields();
}
for (Field field : allFields) {
if (Modifier.isPublic(field.getModifiers()) &&
Modifier.isStatic(field.getModifiers()) &&
(field.getType() == CaptureRequest.Key.class
|| field.getType() == CaptureResult.Key.class
|| field.getType() == TotalCaptureResult.Key.class
|| field.getType() == CameraCharacteristics.Key.class) &&
field.getGenericType() instanceof ParameterizedType) {
ParameterizedType paramType = (ParameterizedType)field.getGenericType();
Type[] argTypes = paramType.getActualTypeArguments();
if (argTypes.length > 0) {
try {
Type keyType = argTypes[0];
Object keyObj = field.get(md);
MetadataEntry entry;
if (keyType instanceof GenericArrayType) {
entry = serializeArrayEntry(keyType, keyObj, md);
} else {
entry = serializeEntry(keyType, keyObj, md);
}
// TODO: Figure this weird case out.
// There is a weird case where the entry is non-null but the toString
// of the entry is null, and if this happens, the null-ness spreads like
// a virus and makes the whole JSON object null from the top level down.
// Not sure if it's a bug in the library or I'm just not using it right.
// Workaround by checking for this case explicitly and not adding the
// value to the jsonObj when it is detected.
if (entry != null && entry.key != null && entry.value != null
&& entry.value.toString() == null) {
Logt.w(TAG, "Error encountered serializing value for key: " + entry.key);
} else if (entry != null) {
jsonObj.put(entry.key, entry.value);
} else {
// Ignore.
}
} catch (IllegalAccessException e) {
throw new ItsException(
"Access error for field: " + field + ": ", e);
} catch (org.json.JSONException e) {
throw new ItsException(
"JSON error for field: " + field + ": ", e);
}
}
}
}
return jsonObj;
}
@SuppressWarnings("unchecked")
public static CaptureRequest.Builder deserialize(CaptureRequest.Builder mdDefault,
JSONObject jsonReq) throws ItsException {
try {
Logt.i(TAG, "Parsing JSON capture request ...");
// Iterate over the CaptureRequest reflected fields.
CaptureRequest.Builder md = mdDefault;
Field[] allFields = CaptureRequest.class.getDeclaredFields();
for (Field field : allFields) {
if (Modifier.isPublic(field.getModifiers()) &&
Modifier.isStatic(field.getModifiers()) &&
field.getType() == CaptureRequest.Key.class &&
field.getGenericType() instanceof ParameterizedType) {
ParameterizedType paramType = (ParameterizedType)field.getGenericType();
Type[] argTypes = paramType.getActualTypeArguments();
if (argTypes.length > 0) {
CaptureRequest.Key key = (CaptureRequest.Key)field.get(md);
String keyName = key.getName();
Type keyType = argTypes[0];
// For each reflected CaptureRequest entry, look inside the JSON object
// to see if it is being set. If it is found, remove the key from the
// JSON object. After this process, there should be no keys left in the
// JSON (otherwise an invalid key was specified).
if (jsonReq.has(keyName) && !jsonReq.isNull(keyName)) {
if (keyType instanceof GenericArrayType) {
Type elmtType =
((GenericArrayType)keyType).getGenericComponentType();
JSONArray ja = jsonReq.getJSONArray(keyName);
Object val[] = new Object[ja.length()];
for (int i = 0; i < ja.length(); i++) {
if (elmtType == int.class) {
Array.set(val, i, ja.getInt(i));
} else if (elmtType == byte.class) {
Array.set(val, i, (byte)ja.getInt(i));
} else if (elmtType == float.class) {
Array.set(val, i, (float)ja.getDouble(i));
} else if (elmtType == long.class) {
Array.set(val, i, ja.getLong(i));
} else if (elmtType == double.class) {
Array.set(val, i, ja.getDouble(i));
} else if (elmtType == boolean.class) {
Array.set(val, i, ja.getBoolean(i));
} else if (elmtType == String.class) {
Array.set(val, i, ja.getString(i));
} else if (elmtType == Size.class){
JSONObject obj = ja.getJSONObject(i);
Array.set(val, i, new Size(
obj.getInt("width"), obj.getInt("height")));
} else if (elmtType == Rect.class) {
JSONObject obj = ja.getJSONObject(i);
Array.set(val, i, new Rect(
obj.getInt("left"), obj.getInt("top"),
obj.getInt("bottom"), obj.getInt("right")));
} else if (elmtType == Rational.class) {
JSONObject obj = ja.getJSONObject(i);
Array.set(val, i, new Rational(
obj.getInt("numerator"),
obj.getInt("denominator")));
} else if (elmtType == RggbChannelVector.class) {
JSONArray arr = ja.getJSONArray(i);
Array.set(val, i, new RggbChannelVector(
(float)arr.getDouble(0),
(float)arr.getDouble(1),
(float)arr.getDouble(2),
(float)arr.getDouble(3)));
} else if (elmtType == ColorSpaceTransform.class) {
JSONArray arr = ja.getJSONArray(i);
Rational xform[] = new Rational[9];
for (int j = 0; j < 9; j++) {
xform[j] = new Rational(
arr.getJSONObject(j).getInt("numerator"),
arr.getJSONObject(j).getInt("denominator"));
}
Array.set(val, i, new ColorSpaceTransform(xform));
} else if (elmtType == MeteringRectangle.class) {
JSONObject obj = ja.getJSONObject(i);
Array.set(val, i, new MeteringRectangle(
obj.getInt("x"),
obj.getInt("y"),
obj.getInt("width"),
obj.getInt("height"),
obj.getInt("weight")));
} else {
throw new ItsException(
"Failed to parse key from JSON: " + keyName);
}
}
if (val != null) {
Logt.i(TAG, "Set: "+keyName+" -> "+Arrays.toString(val));
md.set(key, val);
jsonReq.remove(keyName);
}
} else {
Object val = null;
if (keyType == Integer.class) {
val = jsonReq.getInt(keyName);
} else if (keyType == Byte.class) {
val = (byte)jsonReq.getInt(keyName);
} else if (keyType == Double.class) {
val = jsonReq.getDouble(keyName);
} else if (keyType == Long.class) {
val = jsonReq.getLong(keyName);
} else if (keyType == Float.class) {
val = (float)jsonReq.getDouble(keyName);
} else if (keyType == Boolean.class) {
val = jsonReq.getBoolean(keyName);
} else if (keyType == String.class) {
val = jsonReq.getString(keyName);
} else if (keyType == Size.class) {
JSONObject obj = jsonReq.getJSONObject(keyName);
val = new Size(
obj.getInt("width"), obj.getInt("height"));
} else if (keyType == Rect.class) {
JSONObject obj = jsonReq.getJSONObject(keyName);
val = new Rect(
obj.getInt("left"), obj.getInt("top"),
obj.getInt("right"), obj.getInt("bottom"));
} else if (keyType == Rational.class) {
JSONObject obj = jsonReq.getJSONObject(keyName);
val = new Rational(obj.getInt("numerator"),
obj.getInt("denominator"));
} else if (keyType == RggbChannelVector.class) {
JSONObject obj = jsonReq.optJSONObject(keyName);
JSONArray arr = jsonReq.optJSONArray(keyName);
if (arr != null) {
val = new RggbChannelVector(
(float)arr.getDouble(0),
(float)arr.getDouble(1),
(float)arr.getDouble(2),
(float)arr.getDouble(3));
} else if (obj != null) {
val = new RggbChannelVector(
(float)obj.getDouble("red"),
(float)obj.getDouble("greenEven"),
(float)obj.getDouble("greenOdd"),
(float)obj.getDouble("blue"));
} else {
throw new ItsException("Invalid RggbChannelVector object");
}
} else if (keyType == ColorSpaceTransform.class) {
JSONArray arr = jsonReq.getJSONArray(keyName);
Rational a[] = new Rational[9];
for (int i = 0; i < 9; i++) {
a[i] = new Rational(
arr.getJSONObject(i).getInt("numerator"),
arr.getJSONObject(i).getInt("denominator"));
}
val = new ColorSpaceTransform(a);
} else if (keyType instanceof ParameterizedType &&
((ParameterizedType)keyType).getRawType() == Range.class &&
((ParameterizedType)keyType).getActualTypeArguments().length == 1 &&
((ParameterizedType)keyType).getActualTypeArguments()[0] == Integer.class) {
JSONArray arr = jsonReq.getJSONArray(keyName);
val = new Range<Integer>(arr.getInt(0), arr.getInt(1));
} else {
throw new ItsException(
"Failed to parse key from JSON: " +
keyName + ", " + keyType);
}
if (val != null) {
Logt.i(TAG, "Set: " + keyName + " -> " + val);
md.set(key ,val);
jsonReq.remove(keyName);
}
}
}
}
}
}
// Ensure that there were no invalid keys in the JSON request object.
if (jsonReq.length() != 0) {
throw new ItsException("Invalid JSON key(s): " + jsonReq.toString());
}
Logt.i(TAG, "Parsing JSON capture request completed");
return md;
} catch (java.lang.IllegalAccessException e) {
throw new ItsException("Access error: ", e);
} catch (org.json.JSONException e) {
throw new ItsException("JSON error: ", e);
}
}
@SuppressWarnings("unchecked")
public static List<CaptureRequest.Builder> deserializeRequestList(
CameraDevice device, JSONObject jsonObjTop)
throws ItsException {
try {
List<CaptureRequest.Builder> requests = null;
JSONArray jsonReqs = jsonObjTop.getJSONArray("captureRequests");
requests = new LinkedList<CaptureRequest.Builder>();
for (int i = 0; i < jsonReqs.length(); i++) {
CaptureRequest.Builder templateReq = device.createCaptureRequest(
CameraDevice.TEMPLATE_STILL_CAPTURE);
requests.add(
deserialize(templateReq, jsonReqs.getJSONObject(i)));
}
return requests;
} catch (org.json.JSONException e) {
throw new ItsException("JSON error: ", e);
} catch (android.hardware.camera2.CameraAccessException e) {
throw new ItsException("Access error: ", e);
}
}
}