diff options
| -rw-r--r-- | core/java/android/hardware/Camera.java | 158 | ||||
| -rw-r--r-- | include/camera/CameraParameters.h | 38 | ||||
| -rw-r--r-- | libs/camera/CameraParameters.cpp | 2 |
3 files changed, 198 insertions, 0 deletions
diff --git a/core/java/android/hardware/Camera.java b/core/java/android/hardware/Camera.java index e525c95..0a13b4e6 100644 --- a/core/java/android/hardware/Camera.java +++ b/core/java/android/hardware/Camera.java @@ -27,6 +27,7 @@ import android.util.Log; import android.view.Surface; import android.view.SurfaceHolder; import android.graphics.ImageFormat; +import android.graphics.Rect; import android.graphics.SurfaceTexture; import android.os.Handler; import android.os.Looper; @@ -1083,6 +1084,52 @@ public class Camera { }; /** + * Area class for focus. + * + * @see #setFocusAreas(List<Area>) + * @see #getFocusAreas() + * @hide + */ + public static class Area { + /** + * Create an area with specified rectangle and weight. + * + * @param rect the rectangle of the area + * @param weight the weight of the area + */ + public Area(Rect rect, int weight) { + this.rect = rect; + this.weight = weight; + } + /** + * Compares {@code obj} to this area. + * + * @param obj the object to compare this area with. + * @return {@code true} if the rectangle and weight of {@code obj} is + * the same as those of this area. {@code false} otherwise. + */ + @Override + public boolean equals(Object obj) { + if (!(obj instanceof Area)) { + return false; + } + Area a = (Area) obj; + if (rect == null) { + if (a.rect != null) return false; + } else { + if (!rect.equals(a.rect)) return false; + } + return weight == a.weight; + } + + /** rectangle of the area */ + public Rect rect; + + /** weight of the area */ + public int weight; + }; + + /** * Camera service settings. * * <p>To make camera parameters take effect, applications have to call @@ -1124,6 +1171,8 @@ public class Camera { private static final String KEY_SCENE_MODE = "scene-mode"; private static final String KEY_FLASH_MODE = "flash-mode"; private static final String KEY_FOCUS_MODE = "focus-mode"; + private static final String KEY_FOCUS_AREAS = "focus-areas"; + private static final String KEY_MAX_NUM_FOCUS_AREAS = "max-num-focus-areas"; private static final String KEY_FOCAL_LENGTH = "focal-length"; private static final String KEY_HORIZONTAL_VIEW_ANGLE = "horizontal-view-angle"; private static final String KEY_VERTICAL_VIEW_ANGLE = "vertical-view-angle"; @@ -2499,6 +2548,89 @@ public class Camera { splitFloat(get(KEY_FOCUS_DISTANCES), output); } + /** + * Gets the maximum number of focus areas supported. This is the maximum + * length of the list in {@link #setFocusArea(List<Area>)} and + * {@link #getFocusArea()}. + * + * @return the maximum number of focus areas supported by the camera. + * @see #getFocusAreas() + * @hide + */ + public int getMaxNumFocusAreas() { + return getInt(KEY_MAX_NUM_FOCUS_AREAS, 0); + } + + /** + * Gets the current focus areas. + * + * Before using this API or {@link #setFocusAreas(List<int>)}, apps + * should call {@link #getMaxNumFocusArea()} to know the maximum number of + * focus areas first. If the value is 0, focus area is not supported. + * + * Each focus area is a rectangle with specified weight. The direction + * is relative to the sensor orientation, that is, what the sensor sees. + * The direction is not affected by the rotation or mirroring of + * {@link #setDisplayOrientation(int)}. Coordinates of the rectangle + * range from -1000 to 1000. (-1000, -1000) is the upper left point. + * (1000, 1000) is the lower right point. The length and width of focus + * areas cannot be 0 or negative. + * + * The weight ranges from 1 to 1000. The sum of the weights of all focus + * areas must be 1000. Focus areas can partially overlap and the driver + * will add the weights in the overlap region. But apps should not set + * two focus areas that have identical coordinates. + * + * A special case of all-zero single focus area means driver to decide + * the focus area. For example, the driver may use more signals to + * decide focus areas and change them dynamically. Apps can set all-zero + * if they want the driver to decide focus areas. + * + * Focus areas are relative to the current field of view + * ({@link #getZoom()}). No matter what the zoom level is, (-1000,-1000) + * represents the top of the currently visible camera frame. The focus + * area cannot be set to be outside the current field of view, even + * when using zoom. + * + * Focus area only has effect if the current focus mode is + * {@link #FOCUS_MODE_AUTO}, {@link #FOCUS_MODE_MACRO}, or + * {@link #FOCUS_MODE_CONTINOUS_VIDEO}. + * + * @return a list of current focus areas + * @hide + */ + public List<Area> getFocusAreas() { + return splitArea(KEY_FOCUS_AREAS); + } + + /** + * Sets focus areas. See {@link #getFocusAreas()} for documentation. + * + * @param focusArea the focus areas + * @see #getFocusAreas() + * @hide + */ + public void setFocusAreas(List<Area> focusArea) { + StringBuilder buffer = new StringBuilder(); + for (int i = 0; i < focusArea.size(); i++) { + Area area = focusArea.get(i); + Rect rect = area.rect; + buffer.append('('); + buffer.append(rect.left); + buffer.append(','); + buffer.append(rect.top); + buffer.append(','); + buffer.append(rect.right); + buffer.append(','); + buffer.append(rect.bottom); + buffer.append(','); + buffer.append(area.weight); + buffer.append(')'); + if (i != focusArea.size() - 1) buffer.append(','); + } + set(KEY_FOCUS_AREAS, buffer.toString()); + } + // Splits a comma delimited string to an ArrayList of String. // Return null if the passing string is null or the size is 0. private ArrayList<String> split(String str) { @@ -2624,5 +2756,31 @@ public class Camera { if (rangeList.size() == 0) return null; return rangeList; } + + // Splits a comma delimited string to an ArrayList of Area objects. + // Example string: "(-10,-10,0,0,300),(0,0,10,10,700)". Return null if + // the passing string is null or the size is 0. + private ArrayList<Area> splitArea(String str) { + if (str == null || str.charAt(0) != '(' + || str.charAt(str.length() - 1) != ')') { + Log.e(TAG, "Invalid area string=" + str); + return null; + } + + ArrayList<Area> result = new ArrayList<Area>(); + int endIndex, fromIndex = 1; + int[] array = new int[5]; + do { + endIndex = str.indexOf("),(", fromIndex); + if (endIndex == -1) endIndex = str.length() - 1; + splitInt(str.substring(fromIndex, endIndex), array); + Rect rect = new Rect(array[0], array[1], array[2], array[3]); + result.add(new Area(rect, array[4])); + fromIndex = endIndex + 3; + } while (endIndex != str.length() - 1); + + if (result.size() == 0) return null; + return result; + } }; } diff --git a/include/camera/CameraParameters.h b/include/camera/CameraParameters.h index da2f049..7930f47 100644 --- a/include/camera/CameraParameters.h +++ b/include/camera/CameraParameters.h @@ -247,6 +247,44 @@ public: // Supported focus modes. // Example value: "auto,macro,fixed". Read only. static const char KEY_SUPPORTED_FOCUS_MODES[]; + // The maximum number of focus areas supported. This is the maximum length + // of KEY_FOCUS_AREAS. + // Example value: "0" or "2". Read only. + static const char KEY_MAX_NUM_FOCUS_AREAS[]; + // Current focus areas. + // + // Before accessing this parameter, apps should check + // KEY_MAX_NUM_FOCUS_AREAS first to know the maximum number of focus areas + // first. If the value is 0, focus area is not supported. + // + // Each focus area is a five-element int array. The first four elements are + // the rectangle of the area (left, top, right, bottom). The direction is + // relative to the sensor orientation, that is, what the sensor sees. The + // direction is not affected by the rotation or mirroring of + // CAMERA_CMD_SET_DISPLAY_ORIENTATION. Coordinates range from -1000 to 1000. + // (-1000,-1000) is the upper left point. (1000, 1000) is the lower right + // point. The length and width of focus areas cannot be 0 or negative. + // + // The fifth element is the weight. The weight ranges from 1 to 1000. + // The sum of the weights of all focus areas must be 1000. Focus areas + // can partially overlap and the driver will add the weights in the + // overlap region. But apps should not set two focus areas that have + // identical coordinates. + // + // A special case of single focus area (0,0,0,0,0) means driver to decide + // the focus area. For example, the driver may use more signals to decide + // focus areas and change them dynamically. Apps can set (0,0,0,0,0) if they + // want the driver to decide focus areas. + // + // Focus areas are relative to the current field of view (KEY_ZOOM). No + // matter what the zoom level is, (-1000,-1000) represents the top of the + // currently visible camera frame. The focus area cannot be set to be + // outside the current field of view, even when using zoom. + // + // Focus area only has effect if the current focus mode is FOCUS_MODE_AUTO, + // FOCUS_MODE_MACRO, or FOCUS_MODE_CONTINOUS_VIDEO. + // Example value: "(-10,-10,0,0,300),(0,0,10,10,700)". Read/write. + static const char KEY_FOCUS_AREAS[]; // Focal length in millimeter. // Example value: "4.31". Read only. static const char KEY_FOCAL_LENGTH[]; diff --git a/libs/camera/CameraParameters.cpp b/libs/camera/CameraParameters.cpp index 0fd79a4..1e7abae 100644 --- a/libs/camera/CameraParameters.cpp +++ b/libs/camera/CameraParameters.cpp @@ -59,6 +59,8 @@ const char CameraParameters::KEY_FLASH_MODE[] = "flash-mode"; const char CameraParameters::KEY_SUPPORTED_FLASH_MODES[] = "flash-mode-values"; const char CameraParameters::KEY_FOCUS_MODE[] = "focus-mode"; const char CameraParameters::KEY_SUPPORTED_FOCUS_MODES[] = "focus-mode-values"; +const char CameraParameters::KEY_MAX_NUM_FOCUS_AREAS[] = "max-num-focus-areas"; +const char CameraParameters::KEY_FOCUS_AREAS[] = "focus-areas"; const char CameraParameters::KEY_FOCAL_LENGTH[] = "focal-length"; const char CameraParameters::KEY_HORIZONTAL_VIEW_ANGLE[] = "horizontal-view-angle"; const char CameraParameters::KEY_VERTICAL_VIEW_ANGLE[] = "vertical-view-angle"; |
