Camera API 介绍系列文章:
Android Camera之 --- Camera API说明(一)
Android Camera之 --- Camera API说明(二)
Android Camera之 --- Camera API说明(三)
推荐大家浏览Android源码最便利的方法:
从Android5.0开始google引入新的Camera API,位于:http://androidxref.com/5.0.0_r2/xref/frameworks/base/core/java/android/hardware/camera2/
后续我会写几篇关于Camera2 API的分析文章。
Android Camera API说明:
Camera API基本上有三大功能,预览;拍照;录像,所有对Camera API的调用基本上就是围绕这三种功能来进行的。
Android Camera API 实现位于/frameworks/base/core/java/android/hardware/Camera.java
首先,在开发Camera相关APP时需要在AndroidManifest.xml中申请camera使用权限以及其他有关camera的feature,如:
uses-permission android:name="android.permission.CAMERA"
uses-feature android:name="android.hardware.camera"
uses-feature android:name="android.hardware.camera.autofocus"
预览操作:
1. 通过调用open()或者open(int cameraId)来获取Camera实例;
2. 通过调用getParameters()来获取camera默认的参数集;
3. 根据需要通过Parameters封装的函数来更改必要的参数;
4. 设置参数调用setParameters(Camera.Parameters);
5. 必须调用setPreviewDisplay(SurfaceHolder)来设置预览图像的显示,若没有Surface,camera不能开始预览;
6. 调用startPreview()来开始预览;
7. 想要停止预览则调用stopPreview();
拍照操作:
1. 确保camera已经在预览模式;
2. 调用takePicture(Camera.ShutterCallback, Camera.PictureCallback, Camera.PictureCallback, Camera.PictureCallback)来拍照;
3. 等待takePicture()函数设置的callback返回图片数据;
4. 当takePicture()函数被调用后,预览画面就会停止,想要继续预览或者拍照,则必须调用startPreview()开始预览;
视频录制操作:
1. 确保Camera已经在预览模式;
2. 调用unlock()通知cameraserver允许mediaserver进程访问Camera;
3. 调用MediaRecorder初始化MediaRecorder实例并设置相应的音频视频参数;
4. 调用MediaRecorder.setCamera(Camera)接口将此camera实例做为video datasource;
5. 调用MediaRecorder相关的函数进行视频录制;
6. 结束视频录制也是由MediaRecorder相关的函数来控制;
7. 调用reconnect()接口来对camera实例重新上锁;
介绍完大致的操作步骤后首先对Camera的内部类进行说明:
public static class CameraInfo {
public static final int CAMERA_FACING_BACK = 0; // 在屏幕的相反侧,也就是代表后置摄像头
public static final int CAMERA_FACING_FRONT = 1; // 在屏幕的同侧,代表前置摄像头
public int facing; // 上面定义的两选其一,代表次摄像头的相对位置
public int orientation; // 相机的转角,一般有0,90,180,270.
public boolean canDisableShutterSound; // 是否支持拍照关闭声音
};
若要想Camera参数设置生效,则必须调用Camera.setParameters(Camera.Parameters)接口来设置修改后的Camera参数集。例如:
当调用Camera.Parameters.setWhiteBalance()时,并不能让WB生效,必须通过调用Camera.setParameters(Camera.Parameters)来让修改后的参数集设置生效;不同的硬件有不同的参数功能,比如所支持的preview size和flash mode都是有所不同的,使用者必须首先获取所支持的参数信息,进一步根据所支持的信息来设置相应的参数。下面介绍camera的参数集Camera.Parameters内部类:
@Deprecated
public class Parameters {
// 从下面的定义可以看出每一个参数都是通过key-value来存储的,代表了camera硬件设备的特性和性能,也有一部分是作为设置参数存在的
// Parameter keys to communicate with the camera driver.
// 预览画面大小,一般有默认值,可以通过调用getPreviewSize()来获取默认值,
// 使用者调用getSupportedPreviewSizes()获取所支持的preview size,进而调用setPreviewSize(int width, int height)来设置预览大小;
private static final String KEY_PREVIEW_SIZE = "preview-size";
// previewCallback()返回数据格式,可以通过调用getPreviewFormat()来获取默认值,
// 使用者调用getSupportedPreviewFormats()获取所支持的颜色格式,进而调用setPreviewFormat(int pixel_format)来设置callback数据格式;
private static final String KEY_PREVIEW_FORMAT = "preview-format";
// 预览帧率,使用者调用getPreviewFrameRate()来获取默认的预览帧率,
// 使用者可以通过getSupportedPreviewFrameRates()来获取所支持的预览帧率,进而调用
private static final String KEY_PREVIEW_FRAME_RATE = "preview-frame-rate";
// 用来替代KEY_PREVIEW_FRAME_RATE而设置的,因为camera设备的帧率是不固定的,根据光照条件的差异,曝光时间是不同的,若想得到较好的图像质量,
// 则必须牺牲帧率,所以此处的预览帧率是一个范围,有最大值和最小值之分,可以通过getPreviewFpsRange(int[] range)来获取默认值,
// getSupportedPreviewFpsRange()来获取所支持的预览帧率范围,进而通过setPreviewFpsRange(int min, int max)来设置预览帧率范围,
private static final String KEY_PREVIEW_FPS_RANGE = "preview-fps-range";
// 拍照图片大小,可以通过getPictureSize()来获取默认值,
// 使用者getSupportedPictureSizes()来获取所支持的拍照图片大小,进而通过setPictureSize(int width, int height)来设置拍照图片大小
private static final String KEY_PICTURE_SIZE = "picture-size";
// 拍照图像格式,可以通过getPictureFormat()来获取默认的拍照图片格式,
// 使用者通过getSupportedPictureFormats()来获取所支持的拍照图片格式,进而通过setPictureFormat(int pixel_format)来设置拍照图片格式
private static final String KEY_PICTURE_FORMAT = "picture-format";
// 获取所支持的拍照Thumbnail大小,分别为width和height
private static final String KEY_JPEG_THUMBNAIL_SIZE = "jpeg-thumbnail-size";
// 拍照Thumbnail宽度,通过getJpegThumbnailSize()获取,通过setJpegThumbnailSize(int width, int height)来设置
private static final String KEY_JPEG_THUMBNAIL_WIDTH = "jpeg-thumbnail-width";
// 拍照Thumbnail高度,通过getJpegThumbnailSize()获取,通过setJpegThumbnailSize(int width, int height)来设置
private static final String KEY_JPEG_THUMBNAIL_HEIGHT = "jpeg-thumbnail-height";
// EXIF Thumbnail 图像质量级别[0~100], 100为最佳图像质量,
// 可通过getJpegThumbnailQuality()和setJpegThumbnailQuality(int quality)来获取和设置Thumbnail图像的质量;
private static final String KEY_JPEG_THUMBNAIL_QUALITY = "jpeg-thumbnail-quality";
// 拍照图片JPEG图像质量, 通过setJpegQuality(int quality)和getJpegQuality()来设置或获取图片质量
private static final String KEY_JPEG_QUALITY = "jpeg-quality";
// 设置图像旋转角度,0,90,180,270.
private static final String KEY_ROTATION = "rotation";
// GPS纬度信息,用于拍照
private static final String KEY_GPS_LATITUDE = "gps-latitude";
// GPS经度信息,用于拍照
private static final String KEY_GPS_LONGITUDE = "gps-longitude";
// GPS海拔信息,用于拍照
private static final String KEY_GPS_ALTITUDE = "gps-altitude";
// GPS时间信息,用于拍照
private static final String KEY_GPS_TIMESTAMP = "gps-timestamp";
// GPS信息处理方式,用于拍照
private static final String KEY_GPS_PROCESSING_METHOD = "gps-processing-method";
// 相机WB模式,可通过getSupportedWhiteBalance()来获取所支持的模式,
// 模式有:AUTO,INCANDESCENT,FLUORESCENT,WARM_FLUORESCENT,DAYLIGHT,CLOUDY_DAYLIGHT,TWILIGHT,SHADE,
// 通过String getWhiteBalance()和setWhiteBalance(String value)来获取或设置WB模式
private static final String KEY_WHITE_BALANCE = "whitebalance";
// 预览色彩效果,可通过getSupportedColorEffects()获取所支持的色彩效果,
// 色彩效果有NONE,MONO,NEGATIVE,SOLARIZE,SEPIA,POSTERIZE,WHITEBOARD,BLACKBOARD,AQUA,
// 通过getColorEffect()和setColorEffect(String value)来获取和设置色彩效果
private static final String KEY_EFFECT = "effect";
// antibanding 模式, 可以通过getSupportedAntibanding()来获取所支持的antibanding,
// Antibanding模式有:AUTO,50HZ,60HZ,OFF
// 可以通过getAntibanding()和setAntibanding(String antibanding)来获取或者设置Antibanding模式,
private static final String KEY_ANTIBANDING = "antibanding";
// 场景模式,可以通过getSupportedSceneModes()来获取所支持的场景模式
// 场景模式有: AUTO,ACTION,PORTRAIT,LANDSCAPE,NIGHT,NIGHT_PORTRAIT,
// THEATRE,BEACH,SNOW,SUNSET,STEADYPHOTO,FIREWORKS,SPORTS,PARTY,
// CANDLELIGHT, BARCODE
// 可以通过getSceneMode()和setSceneMode(String value)来获取或设置场景模式,
private static final String KEY_SCENE_MODE = "scene-mode";
// 闪光灯模式,可以通过getSupportedFlashModes()来获取所支持的闪光灯模式
// 闪光灯模式: OFF,AUTO,ON,RED_EYE,TORCH
// 可以通过getFlashMode()和setFlashMode(String value)来获取或设置闪光灯模式,
private static final String KEY_FLASH_MODE = "flash-mode";
// 拍照对焦模式, 可以通过getSupportedFocusModes()来获取所支持的对焦模式,
// 对焦模式有:AUTO,INFINITY,MACRO,FIXED,EDOF,CONTINUOUS_VIDEO
// 可以通过getFocusMode()和setFocusMode(String value)来获取或设置对焦模式,
private static final String KEY_FOCUS_MODE = "focus-mode";
// 对焦区域, getFocusAreas()和setFocusAreas(List<Area> focusAreas)用来获取或设置对焦区域
private static final String KEY_FOCUS_AREAS = "focus-areas";
// 对焦区域的最大个数
private static final String KEY_MAX_NUM_FOCUS_AREAS = "max-num-focus-areas";
// 焦距, 可以调用getFocalLength()来获取焦距长度
private static final String KEY_FOCAL_LENGTH = "focal-length";
// 水平视角,通过getHorizontalViewAngle()获取
private static final String KEY_HORIZONTAL_VIEW_ANGLE = "horizontal-view-angle";
// 垂直视角, 通过getVerticalViewAngle()获取
private static final String KEY_VERTICAL_VIEW_ANGLE = "vertical-view-angle";
// 曝光补偿, 通过getExposureCompensation()和setExposureCompensation(int value)获取或设置曝光补偿序号,
private static final String KEY_EXPOSURE_COMPENSATION = "exposure-compensation";
// 最大曝光补偿序号, 通过getMaxExposureCompensation()获取,
private static final String KEY_MAX_EXPOSURE_COMPENSATION = "max-exposure-compensation";
// 最小曝光补偿序号,通过getMinExposureCompensation()获取,
private static final String KEY_MIN_EXPOSURE_COMPENSATION = "min-exposure-compensation";
// 曝光补偿步长,通过getExposureCompensationStep()获取,
private static final String KEY_EXPOSURE_COMPENSATION_STEP = "exposure-compensation-step";
// 自动曝光锁定,通过setAutoExposureLock(boolean toggle)和getAutoExposureLock()来设定或获取自动曝光锁定状态,
private static final String KEY_AUTO_EXPOSURE_LOCK = "auto-exposure-lock";
// 自动曝光锁定是否支持,通过isAutoExposureLockSupported()判定是否支持自动曝光锁定设置,
private static final String KEY_AUTO_EXPOSURE_LOCK_SUPPORTED = "auto-exposure-lock-supported";
// 自动白平衡锁定, 通过setAutoWhiteBalanceLock(boolean toggle)和getAutoWhiteBalanceLock()来设置或获取自动白平衡锁定状态,
private static final String KEY_AUTO_WHITEBALANCE_LOCK = "auto-whitebalance-lock";
// 自动白平衡锁定是否支持,通过isAutoWhiteBalanceLockSupported()判定是否支持自动白平衡锁定设置,
private static final String KEY_AUTO_WHITEBALANCE_LOCK_SUPPORTED = "auto-whitebalance-lock-supported";
// 曝光区域,通过getMeteringAreas()和setMeteringAreas(List<Area> meteringAreas)来获取或设置曝光区域,
private static final String KEY_METERING_AREAS = "metering-areas";
// 曝光区域的最大个数,通过getMaxNumMeteringAreas()来获取
private static final String KEY_MAX_NUM_METERING_AREAS = "max-num-metering-areas";
// 图像缩放,通过getZoom()和setZoom(int value)来获取或设定缩放值
private static final String KEY_ZOOM = "zoom";
// 最大缩放值,通过getMaxZoom()来获取
private static final String KEY_MAX_ZOOM = "max-zoom";
// 缩放比,需要除以100,来表示,3.2x--->320, 第一个值为100, 最后一个为最大缩放比
private static final String KEY_ZOOM_RATIOS = "zoom-ratios";
// 缩放是否支持,通过isZoomSupported()来判定
private static final String KEY_ZOOM_SUPPORTED = "zoom-supported";
// 平滑缩放是否支持,通过isSmoothZoomSupported()来判定
private static final String KEY_SMOOTH_ZOOM_SUPPORTED = "smooth-zoom-supported";
// 像距,对焦时物体到焦点的距离
private static final String KEY_FOCUS_DISTANCES = "focus-distances";
// 获取录像所需的图像大小,通过getSupportedVideoSizes()来获取
private static final String KEY_VIDEO_SIZE = "video-size";
// 获取被推荐的预览图像大小,通过getPreferredPreviewSizeForVideo()获取
private static final String KEY_PREFERRED_PREVIEW_SIZE_FOR_VIDEO =
"preferred-preview-size-for-video";
// 硬件加速人脸识别的支持的最大个数,通过getMaxNumDetectedFaces()来获取
private static final String KEY_MAX_NUM_DETECTED_FACES_HW = "max-num-detected-faces-hw";
// 软件人脸识别的支持的最大个数
private static final String KEY_MAX_NUM_DETECTED_FACES_SW = "max-num-detected-faces-sw";
// 暗示将会开启视频录制,而不是照相,通过setRecordingHint(boolean hint)来设置
private static final String KEY_RECORDING_HINT = "recording-hint";
// 视频录制时是否支持快照,通过isVideoSnapshotSupported()来获取值
private static final String KEY_VIDEO_SNAPSHOT_SUPPORTED = "video-snapshot-supported";
// 在相机预览或视频录制时开启或关闭抖动抑制,不能在拍照时抑制运动模糊
private static final String KEY_VIDEO_STABILIZATION = "video-stabilization";
// 视频稳定特性是否支持,通过isVideoStabilizationSupported()来获取
private static final String KEY_VIDEO_STABILIZATION_SUPPORTED = "video-stabilization-supported";
// Parameter key suffix for supported values.
private static final String SUPPORTED_VALUES_SUFFIX = "-values";
private static final String TRUE = "true";
private static final String FALSE = "false";
// Values for white balance settings.
public static final String WHITE_BALANCE_AUTO = "auto";
public static final String WHITE_BALANCE_INCANDESCENT = "incandescent";
public static final String WHITE_BALANCE_FLUORESCENT = "fluorescent";
public static final String WHITE_BALANCE_WARM_FLUORESCENT = "warm-fluorescent";
public static final String WHITE_BALANCE_DAYLIGHT = "daylight";
public static final String WHITE_BALANCE_CLOUDY_DAYLIGHT = "cloudy-daylight";
public static final String WHITE_BALANCE_TWILIGHT = "twilight";
public static final String WHITE_BALANCE_SHADE = "shade";
// Values for color effect settings.
public static final String EFFECT_NONE = "none";
public static final String EFFECT_MONO = "mono";
public static final String EFFECT_NEGATIVE = "negative";
public static final String EFFECT_SOLARIZE = "solarize";
public static final String EFFECT_SEPIA = "sepia";
public static final String EFFECT_POSTERIZE = "posterize";
public static final String EFFECT_WHITEBOARD = "whiteboard";
public static final String EFFECT_BLACKBOARD = "blackboard";
public static final String EFFECT_AQUA = "aqua";
// Values for antibanding settings.
public static final String ANTIBANDING_AUTO = "auto";
public static final String ANTIBANDING_50HZ = "50hz";
public static final String ANTIBANDING_60HZ = "60hz";
public static final String ANTIBANDING_OFF = "off";
// Values for flash mode settings.
/**
* Flash will not be fired.
*/
public static final String FLASH_MODE_OFF = "off";
/**
* Flash will be fired automatically when required. The flash may be fired
* during preview, auto-focus, or snapshot depending on the driver.
*/
public static final String FLASH_MODE_AUTO = "auto";
/**
* Flash will always be fired during snapshot. The flash may also be
* fired during preview or auto-focus depending on the driver.
*/
public static final String FLASH_MODE_ON = "on";
/**
* Flash will be fired in red-eye reduction mode.
*/
public static final String FLASH_MODE_RED_EYE = "red-eye";
/**
* Constant emission of light during preview, auto-focus and snapshot.
* This can also be used for video recording.
*/
public static final String FLASH_MODE_TORCH = "torch";
/**
* Scene mode is off.
*/
public static final String SCENE_MODE_AUTO = "auto";
/**
* Take photos of fast moving objects. Same as {@link
* #SCENE_MODE_SPORTS}.
*/
public static final String SCENE_MODE_ACTION = "action";
/**
* Take people pictures.
*/
public static final String SCENE_MODE_PORTRAIT = "portrait";
/**
* Take pictures on distant objects.
*/
public static final String SCENE_MODE_LANDSCAPE = "landscape";
/**
* Take photos at night.
*/
public static final String SCENE_MODE_NIGHT = "night";
/**
* Take people pictures at night.
*/
public static final String SCENE_MODE_NIGHT_PORTRAIT = "night-portrait";
/**
* Take photos in a theater. Flash light is off.
*/
public static final String SCENE_MODE_THEATRE = "theatre";
/**
* Take pictures on the beach.
*/
public static final String SCENE_MODE_BEACH = "beach";
/**
* Take pictures on the snow.
*/
public static final String SCENE_MODE_SNOW = "snow";
/**
* Take sunset photos.
*/
public static final String SCENE_MODE_SUNSET = "sunset";
/**
* Avoid blurry pictures (for example, due to hand shake).
*/
public static final String SCENE_MODE_STEADYPHOTO = "steadyphoto";
/**
* For shooting firework displays.
*/
public static final String SCENE_MODE_FIREWORKS = "fireworks";
/**
* Take photos of fast moving objects. Same as {@link
* #SCENE_MODE_ACTION}.
*/
public static final String SCENE_MODE_SPORTS = "sports";
/**
* Take indoor low-light shot.
*/
public static final String SCENE_MODE_PARTY = "party";
/**
* Capture the naturally warm color of scenes lit by candles.
*/
public static final String SCENE_MODE_CANDLELIGHT = "candlelight";
/**
* Applications are looking for a barcode. Camera driver will be
* optimized for barcode reading.
*/
public static final String SCENE_MODE_BARCODE = "barcode";
/**
* Capture a scene using high dynamic range imaging techniques. The
* camera will return an image that has an extended dynamic range
* compared to a regular capture. Capturing such an image may take
* longer than a regular capture.
*/
public static final String SCENE_MODE_HDR = "hdr";
/**
* Auto-focus mode. Applications should call {@link
* #autoFocus(AutoFocusCallback)} to start the focus in this mode.
*/
public static final String FOCUS_MODE_AUTO = "auto";
/**
* Focus is set at infinity. Applications should not call
* {@link #autoFocus(AutoFocusCallback)} in this mode.
*/
public static final String FOCUS_MODE_INFINITY = "infinity";
/**
* Macro (close-up) focus mode. Applications should call
* {@link #autoFocus(AutoFocusCallback)} to start the focus in this
* mode.
*/
public static final String FOCUS_MODE_MACRO = "macro";
/**
* Focus is fixed. The camera is always in this mode if the focus is not
* adjustable. If the camera has auto-focus, this mode can fix the
* focus, which is usually at hyperfocal distance. Applications should
* not call {@link #autoFocus(AutoFocusCallback)} in this mode.
*/
public static final String FOCUS_MODE_FIXED = "fixed";
/**
* Extended depth of field (EDOF). Focusing is done digitally and
* continuously. Applications should not call {@link
* #autoFocus(AutoFocusCallback)} in this mode.
*/
public static final String FOCUS_MODE_EDOF = "edof";
/**
* Continuous auto focus mode intended for video recording. The camera
* continuously tries to focus. This is the best choice for video
* recording because the focus changes smoothly . Applications still can
* call {@link #takePicture(Camera.ShutterCallback,
* Camera.PictureCallback, Camera.PictureCallback)} in this mode but the
* subject may not be in focus. Auto focus starts when the parameter is
* set.
*
* <p>Since API level 14, applications can call {@link
* #autoFocus(AutoFocusCallback)} in this mode. The focus callback will
* immediately return with a boolean that indicates whether the focus is
* sharp or not. The focus position is locked after autoFocus call. If
* applications want to resume the continuous focus, cancelAutoFocus
* must be called. Restarting the preview will not resume the continuous
* autofocus. To stop continuous focus, applications should change the
* focus mode to other modes.
*
* @see #FOCUS_MODE_CONTINUOUS_PICTURE
*/
public static final String FOCUS_MODE_CONTINUOUS_VIDEO = "continuous-video";
/**
* Continuous auto focus mode intended for taking pictures. The camera
* continuously tries to focus. The speed of focus change is more
* aggressive than {@link #FOCUS_MODE_CONTINUOUS_VIDEO}. Auto focus
* starts when the parameter is set.
*
* <p>Applications can call {@link #autoFocus(AutoFocusCallback)} in
* this mode. If the autofocus is in the middle of scanning, the focus
* callback will return when it completes. If the autofocus is not
* scanning, the focus callback will immediately return with a boolean
* that indicates whether the focus is sharp or not. The apps can then
* decide if they want to take a picture immediately or to change the
* focus mode to auto, and run a full autofocus cycle. The focus
* position is locked after autoFocus call. If applications want to
* resume the continuous focus, cancelAutoFocus must be called.
* Restarting the preview will not resume the continuous autofocus. To
* stop continuous focus, applications should change the focus mode to
* other modes.
*
* @see #FOCUS_MODE_CONTINUOUS_VIDEO
*/
public static final String FOCUS_MODE_CONTINUOUS_PICTURE = "continuous-picture";
// Indices for focus distance array.
/**
* The array index of near focus distance for use with
* {@link #getFocusDistances(float[])}.
*/
public static final int FOCUS_DISTANCE_NEAR_INDEX = 0;
/**
* The array index of optimal focus distance for use with
* {@link #getFocusDistances(float[])}.
*/
public static final int FOCUS_DISTANCE_OPTIMAL_INDEX = 1;
/**
* The array index of far focus distance for use with
* {@link #getFocusDistances(float[])}.
*/
public static final int FOCUS_DISTANCE_FAR_INDEX = 2;
/**
* The array index of minimum preview fps for use with {@link
* #getPreviewFpsRange(int[])} or {@link
* #getSupportedPreviewFpsRange()}.
*/
public static final int PREVIEW_FPS_MIN_INDEX = 0;
/**
* The array index of maximum preview fps for use with {@link
* #getPreviewFpsRange(int[])} or {@link
* #getSupportedPreviewFpsRange()}.
*/
public static final int PREVIEW_FPS_MAX_INDEX = 1;
// Formats for setPreviewFormat and setPictureFormat.
private static final String PIXEL_FORMAT_YUV422SP = "yuv422sp";
private static final String PIXEL_FORMAT_YUV420SP = "yuv420sp";
private static final String PIXEL_FORMAT_YUV422I = "yuv422i-yuyv";
private static final String PIXEL_FORMAT_YUV420P = "yuv420p";
private static final String PIXEL_FORMAT_RGB565 = "rgb565";
private static final String PIXEL_FORMAT_JPEG = "jpeg";
private static final String PIXEL_FORMAT_BAYER_RGGB = "bayer-rggb";
/**
* Order matters: Keys that are {@link #set(String, String) set} later
* will take precedence over keys that are set earlier (if the two keys
* conflict with each other).
*
* <p>One example is {@link #setPreviewFpsRange(int, int)} , since it
* conflicts with {@link #setPreviewFrameRate(int)} whichever key is set later
* is the one that will take precedence.
* </p>
*/
private final LinkedHashMap<String, String> mMap;
private Parameters() {
mMap = new LinkedHashMap<String, String>(/*initialCapacity*/64);
}
/**
* Overwrite existing parameters with a copy of the ones from {@code other}.
*
* <b>For use by the legacy shim only.</b>
*
* @hide
*/
public void copyFrom(Parameters other) {
if (other == null) {
throw new NullPointerException("other must not be null");
}
mMap.putAll(other.mMap);
}
private Camera getOuter() {
return Camera.this;
}
/**
* Value equality check.
*
* @hide
*/
public boolean same(Parameters other) {
if (this == other) {
return true;
}
return other != null && Parameters.this.mMap.equals(other.mMap);
}
/**
* Writes the current Parameters to the log.
* @hide
* @deprecated
*/
@Deprecated
public void dump() {
Log.e(TAG, "dump: size=" + mMap.size());
for (String k : mMap.keySet()) {
Log.e(TAG, "dump: " + k + "=" + mMap.get(k));
}
}
/**
* Creates a single string with all the parameters set in
* this Parameters object.
* <p>The {@link #unflatten(String)} method does the reverse.</p>
*
* @return a String with all values from this Parameters object, in
* semi-colon delimited key-value pairs
*/
public String flatten() {
StringBuilder flattened = new StringBuilder(128);
for (String k : mMap.keySet()) {
flattened.append(k);
flattened.append("=");
flattened.append(mMap.get(k));
flattened.append(";");
}
// chop off the extra semicolon at the end
flattened.deleteCharAt(flattened.length()-1);
return flattened.toString();
}
/**
* Takes a flattened string of parameters and adds each one to
* this Parameters object.
* <p>The {@link #flatten()} method does the reverse.</p>
*
* @param flattened a String of parameters (key-value paired) that
* are semi-colon delimited
*/
public void unflatten(String flattened) {
mMap.clear();
TextUtils.StringSplitter splitter = new TextUtils.SimpleStringSplitter(';');
splitter.setString(flattened);
for (String kv : splitter) {
int pos = kv.indexOf('=');
if (pos == -1) {
continue;
}
String k = kv.substring(0, pos);
String v = kv.substring(pos + 1);
mMap.put(k, v);
}
}
public void remove(String key) {
mMap.remove(key);
}
/**
* Sets a String parameter.
*
* @param key the key name for the parameter
* @param value the String value of the parameter
*/
public void set(String key, String value) {
if (key.indexOf('=') != -1 || key.indexOf(';') != -1 || key.indexOf(0) != -1) {
Log.e(TAG, "Key \"" + key + "\" contains invalid character (= or ; or \\0)");
return;
}
if (value.indexOf('=') != -1 || value.indexOf(';') != -1 || value.indexOf(0) != -1) {
Log.e(TAG, "Value \"" + value + "\" contains invalid character (= or ; or \\0)");
return;
}
put(key, value);
}
/**
* Sets an integer parameter.
*
* @param key the key name for the parameter
* @param value the int value of the parameter
*/
public void set(String key, int value) {
put(key, Integer.toString(value));
}
private void put(String key, String value) {
/*
* Remove the key if it already exists.
*
* This way setting a new value for an already existing key will always move
* that key to be ordered the latest in the map.
*/
mMap.remove(key);
mMap.put(key, value);
}
private void set(String key, List<Area> areas) {
if (areas == null) {
set(key, "(0,0,0,0,0)");
} else {
StringBuilder buffer = new StringBuilder();
for (int i = 0; i < areas.size(); i++) {
Area area = areas.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 != areas.size() - 1) buffer.append(',');
}
set(key, buffer.toString());
}
}
/**
* Returns the value of a String parameter.
*
* @param key the key name for the parameter
* @return the String value of the parameter
*/
public String get(String key) {
return mMap.get(key);
}
/**
* Returns the value of an integer parameter.
*
* @param key the key name for the parameter
* @return the int value of the parameter
*/
public int getInt(String key) {
return Integer.parseInt(mMap.get(key));
}
// 设置预览画面大小,若预览已经启动,则必须现停止预览,重新设置所需参数,
// 设置此值需综合考虑显示旋转角度;
public void setPreviewSize(int width, int height);
// 获取预览画面大小;
public Size getPreviewSize();
// 获取所支持的预览画面大小参数值,返回一个列表;
public List<Size> getSupportedPreviewSizes();
// 获取所支持的录像图像大小,返回一个列表
public List<Size> getSupportedVideoSizes();
// 获取被推荐的预览图像大小用于预览和录像
public Size getPreferredPreviewSizeForVideo();
// JPEG thumbnail大小设置
public void setJpegThumbnailSize(int width, int height);
// JPEG thumbnail大小获取
public Size getJpegThumbnailSize();
// 获取所支持的拍照Thumbnail大小
public List<Size> getSupportedJpegThumbnailSizes();
// 设置Thumbnail图像质量[0~100], 100为最佳质量
public void setJpegThumbnailQuality(int quality);
// 获取当前Thumbnail图像质量
public int getJpegThumbnailQuality();
// 设置拍照图片图像质量
public void setJpegQuality(int quality);
// 获取拍照图片图像质量
public int getJpegQuality();
// 设置预览帧率,这只是一个预想值,具体要看驱动是否能达到, 后续被setPreviewFpsRange(int,int)替代
public void setPreviewFrameRate(int fps);
// 获取预览帧率,这只是一个预想值,具体要看驱动是否能达到, 后续被getPreviewFpsRange(int[])替代
public int getPreviewFrameRate();
// 获取所支持的预览帧率,返回一个list列表,后续被getSupportedPreviewFpsRange()替代
public List<Integer> getSupportedPreviewFrameRates();
// 设置预览帧率范围,最大值和最小值必须乘以1000,此值用来控制PreviewCallback速率
public void setPreviewFpsRange(int min, int max);
// 获取当前预览帧率最大值和最小值, 计算实际帧率必须除以1000,可以通过PREVIEW_FPS_MIN_INDEX
// PREVIEW_FPS_MAX_INDEX来确定返回数组中那个是最大值,那个是最小值,
public void getPreviewFpsRange(int[] range);
// 获取所支持的预览帧率范围,每一个组值分别有最大值和最小值,返回的是一个列表,
// 期望的实际帧率在所设置的帧率范围之内,
public List<int[]> getSupportedPreviewFpsRange();
// 设置preview时的video数据格式,若没有设置则默认为ImageFormat.NV21,因为在视频录制是所需格式为ImageFormat.NV21;
// 可以通过getSupportedPreviewFormats()来获取所支持的video数据格式,返回一个列表;
// 强烈建议使用ImageFormat.NV21和ImageFormat.YV12,因为绝大多数Camera都支持这两种数据格式;
public void setPreviewFormat(int pixel_format);
// 获取preview时的video数据格式;
public int getPreviewFormat();
// 获取所支持的video数据格式,返回一个列表;
public List<Integer> getSupportedPreviewFormats();
// 设置拍照图片大小
public void setPictureSize(int width, int height);
// 获取当前拍照图片大小
public Size getPictureSize();
// 获取所支持的拍照图片大小,返回一个列表
public List<Size> getSupportedPictureSizes();
// 设置拍照图片格式,期望支持的有ImageFormat.NV21, ImageFormat.RGB_565, ImageFormat.JPEG
public void setPictureFormat(int pixel_format);
// 获取当前拍照图片格式
public int getPictureFormat();
// 获取所支持的拍照图片格式,返回一个列表
public List<Integer> getSupportedPictureFormats();
private String cameraFormatForPixelFormat(int pixel_format) {
switch(pixel_format) {
case ImageFormat.NV16: return PIXEL_FORMAT_YUV422SP;
case ImageFormat.NV21: return PIXEL_FORMAT_YUV420SP;
case ImageFormat.YUY2: return PIXEL_FORMAT_YUV422I;
case ImageFormat.YV12: return PIXEL_FORMAT_YUV420P;
case ImageFormat.RGB_565: return PIXEL_FORMAT_RGB565;
case ImageFormat.JPEG: return PIXEL_FORMAT_JPEG;
default: return null;
}
}
private int pixelFormatForCameraFormat(String format) {
if (format == null)
return ImageFormat.UNKNOWN;
if (format.equals(PIXEL_FORMAT_YUV422SP))
return ImageFormat.NV16;
if (format.equals(PIXEL_FORMAT_YUV420SP))
return ImageFormat.NV21;
if (format.equals(PIXEL_FORMAT_YUV422I))
return ImageFormat.YUY2;
if (format.equals(PIXEL_FORMAT_YUV420P))
return ImageFormat.YV12;
if (format.equals(PIXEL_FORMAT_RGB565))
return ImageFormat.RGB_565;
if (format.equals(PIXEL_FORMAT_JPEG))
return ImageFormat.JPEG;
return ImageFormat.UNKNOWN;
}
// 设置图像旋转角度,0,90,180,270.
public void setRotation(int rotation);
// GPS纬度信息,用于拍照
public void setGpsLatitude(double latitude);
// GPS经度信息,用于拍照
public void setGpsLongitude(double longitude);
// GPS海拔信息,用于拍照
public void setGpsAltitude(double altitude);
// GPS时间信息,用于拍照
public void setGpsTimestamp(long timestamp);
// GPS信息处理方式,用于拍照
public void setGpsProcessingMethod(String processing_method);
/**
* Removes GPS latitude, longitude, altitude, and timestamp from the
* parameters.
*/
public void removeGpsData() {
remove(KEY_GPS_LATITUDE);
remove(KEY_GPS_LONGITUDE);
remove(KEY_GPS_ALTITUDE);
remove(KEY_GPS_TIMESTAMP);
remove(KEY_GPS_PROCESSING_METHOD);
}
// 获取当前WB模式
public String getWhiteBalance();
// 设置WB模式
public void setWhiteBalance(String value);
// 获取所支持的WB模式,模式有:AUTO,INCANDESCENT,FLUORESCENT,WARM_FLUORESCENT,DAYLIGHT,CLOUDY_DAYLIGHT,TWILIGHT,SHADE
public List<String> getSupportedWhiteBalance();
// 获取色彩效果
public String getColorEffect();
// 设置色彩效果
public void setColorEffect(String value);
// 获取camera设备所支持的色彩效果
// 色彩效果有NONE,MONO,NEGATIVE,SOLARIZE,SEPIA,POSTERIZE,WHITEBOARD,BLACKBOARD,AQUA
public List<String> getSupportedColorEffects();
// 获取当前Antibinding模式
public String getAntibanding();
// 设置Antibinding模式
public void setAntibanding(String antibanding);
// 获取设备所支持的Antibinding模式
public List<String> getSupportedAntibanding();
// 获取当前的场景模式,场景模式有:AUTO,ACTION,PORTRAIT,LANDSCAPE,NIGHT,
// NIGHT_PORTRAIT,THEATRE,BEACH, SNOW, SUNSET,STEADYPHOTO,FIREWORKS,SPORTS,PARTY,CANDLELIGHT, BARCODE
public String getSceneMode();
// 设置场景模式
public void setSceneMode(String value);
// 获取所支持的场景模式
public List<String> getSupportedSceneModes();
// 获取当前闪光灯模式
// 闪光灯模式有: OFF,AUTO,ON,RED_EYE,TORCH
public String getFlashMode() {
return get(KEY_FLASH_MODE);
}
// 设置闪光灯模式
public void setFlashMode(String value);
// 设置系统设备所支持的闪光灯模式
public List<String> getSupportedFlashModes();
// 获取当前设备对应的对焦模式
// 对焦模式有: AUTO,INFINITY,MACRO,FIXED,EDOF,CONTINUOUS_VIDEO
public String getFocusMode();
// 设置对焦模式
public void setFocusMode(String value);
// 获取系统所支持的对焦模式
public List<String> getSupportedFocusModes();
// 获取焦距
public float getFocalLength();
// 水平视角
public float getHorizontalViewAngle();
// 垂直视角
public float getVerticalViewAngle();
// 获取当前曝光补偿序号
public int getExposureCompensation();
// 设置曝光补偿序号
public void setExposureCompensation(int value);
// 获取支持的最大曝光补偿序号
public int getMaxExposureCompensation();
// 获取支持的最小曝光补偿序号
public int getMinExposureCompensation();
// 获取曝光补偿步长
public float getExposureCompensationStep();
// 自动曝光锁定,使用者调用前必须通过isAutoExposureLockSupported()判定是否支持该操作,
// 若设置为true,自动曝光程序将立即暂停直到调用此接口设置为false,在自动曝光锁定时,曝光补偿设置仍然是有效的,
// 重复设置自动曝光锁定不影响之前的设定,调用stopPreview()和takePicture()将不会改变锁定状态。
public void setAutoExposureLock(boolean toggle);
// 获取自动曝光锁定状态
public boolean getAutoExposureLock();
// 判定自动曝光锁定是否支持
public boolean isAutoExposureLockSupported();
// 自动白平衡锁定设置,使用者必须通过isAutoWhiteBalanceLockSupported()判定自动白平衡锁定设置是否支持,
// 若设置为true,自动白平衡程序将立即暂停直到调用此接口设置为false,
// 重复设置自动曝光锁定不影响之前的设定,调用stopPreview()和takePicture()将不会改变锁定状态。
public void setAutoWhiteBalanceLock(boolean toggle);
// 获取自动白平衡锁定状态
public boolean getAutoWhiteBalanceLock();
// 判定自动白平衡锁定是否支持
public boolean isAutoWhiteBalanceLockSupported();
// 获取当前的缩放值,范围[0~getMaxZoom()]. 0代表没有缩放,
// 使用之前通过isZoomSupported()判定是否支持缩放
public int getZoom();
// 设置缩放值
public void setZoom(int value);
// 判定缩放是否支持
public boolean isZoomSupported();
// 获取最大缩放值
public int getMaxZoom();
// 缩放比,需要除以100,来表示,3.2x--->320, 第一个值为100, 最后一个为最大缩放比
public List<Integer> getZoomRatios();
// 判定是否支持平滑缩放
public boolean isSmoothZoomSupported();
// 对焦过程中 物体到焦点的距离,会时时变化
public void getFocusDistances(float[] output);
// 对焦区域的最大个数
public int getMaxNumFocusAreas();
// 获取camera的对焦区域
public List<Area> getFocusAreas();
// 设置对焦区域, camera驱动将会使用此区域来进行对焦
public void setFocusAreas(List<Area> focusAreas);
// 获取所支持曝光区域最大个数
public int getMaxNumMeteringAreas();
// 获取当前曝光区域设定
public List<Area> getMeteringAreas();
// 设置曝光区域
public void setMeteringAreas(List<Area> meteringAreas);
// 硬件加速人脸识别的支持的最大个数
public int getMaxNumDetectedFaces();
// 示将会开启视频录制,而不是照相
public void setRecordingHint(boolean hint);
// 视频录制时是否支持快照
public boolean isVideoSnapshotSupported();
// 在相机预览或视频录制时开启或关闭抖动抑制,不能在拍照时抑制运动模糊
public void setVideoStabilization(boolean toggle);
// 获取抖动抑制(视频稳定)状态
public boolean getVideoStabilization();
// 是否支持视频稳定设置
public boolean isVideoStabilizationSupported();
// 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) {
if (str == null) return null;
TextUtils.StringSplitter splitter = new TextUtils.SimpleStringSplitter(',');
splitter.setString(str);
ArrayList<String> substrings = new ArrayList<String>();
for (String s : splitter) {
substrings.add(s);
}
return substrings;
}
// Splits a comma delimited string to an ArrayList of Integer.
// Return null if the passing string is null or the size is 0.
private ArrayList<Integer> splitInt(String str) {
if (str == null) return null;
TextUtils.StringSplitter splitter = new TextUtils.SimpleStringSplitter(',');
splitter.setString(str);
ArrayList<Integer> substrings = new ArrayList<Integer>();
for (String s : splitter) {
substrings.add(Integer.parseInt(s));
}
if (substrings.size() == 0) return null;
return substrings;
}
private void splitInt(String str, int[] output) {
if (str == null) return;
TextUtils.StringSplitter splitter = new TextUtils.SimpleStringSplitter(',');
splitter.setString(str);
int index = 0;
for (String s : splitter) {
output[index++] = Integer.parseInt(s);
}
}
// Splits a comma delimited string to an ArrayList of Float.
private void splitFloat(String str, float[] output) {
if (str == null) return;
TextUtils.StringSplitter splitter = new TextUtils.SimpleStringSplitter(',');
splitter.setString(str);
int index = 0;
for (String s : splitter) {
output[index++] = Float.parseFloat(s);
}
}
// Returns the value of a float parameter.
private float getFloat(String key, float defaultValue) {
try {
return Float.parseFloat(mMap.get(key));
} catch (NumberFormatException ex) {
return defaultValue;
}
}
// Returns the value of a integer parameter.
private int getInt(String key, int defaultValue) {
try {
return Integer.parseInt(mMap.get(key));
} catch (NumberFormatException ex) {
return defaultValue;
}
}
// Splits a comma delimited string to an ArrayList of Size.
// Return null if the passing string is null or the size is 0.
private ArrayList<Size> splitSize(String str) {
if (str == null) return null;
TextUtils.StringSplitter splitter = new TextUtils.SimpleStringSplitter(',');
splitter.setString(str);
ArrayList<Size> sizeList = new ArrayList<Size>();
for (String s : splitter) {
Size size = strToSize(s);
if (size != null) sizeList.add(size);
}
if (sizeList.size() == 0) return null;
return sizeList;
}
// Parses a string (ex: "480x320") to Size object.
// Return null if the passing string is null.
private Size strToSize(String str) {
if (str == null) return null;
int pos = str.indexOf('x');
if (pos != -1) {
String width = str.substring(0, pos);
String height = str.substring(pos + 1);
return new Size(Integer.parseInt(width),
Integer.parseInt(height));
}
Log.e(TAG, "Invalid size parameter string=" + str);
return null;
}
// Splits a comma delimited string to an ArrayList of int array.
// Example string: "(10000,26623),(10000,30000)". Return null if the
// passing string is null or the size is 0.
private ArrayList<int[]> splitRange(String str) {
if (str == null || str.charAt(0) != '('
|| str.charAt(str.length() - 1) != ')') {
Log.e(TAG, "Invalid range list string=" + str);
return null;
}
ArrayList<int[]> rangeList = new ArrayList<int[]>();
int endIndex, fromIndex = 1;
do {
int[] range = new int[2];
endIndex = str.indexOf("),(", fromIndex);
if (endIndex == -1) endIndex = str.length() - 1;
splitInt(str.substring(fromIndex, endIndex), range);
rangeList.add(range);
fromIndex = endIndex + 3;
} while (endIndex != str.length() - 1);
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 or (0,0,0,0,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;
if (result.size() == 1) {
Area area = result.get(0);
Rect rect = area.rect;
if (rect.left == 0 && rect.top == 0 && rect.right == 0
&& rect.bottom == 0 && area.weight == 0) {
return null;
}
}
return result;
}
private boolean same(String s1, String s2) {
if (s1 == null && s2 == null) return true;
if (s1 != null && s1.equals(s2)) return true;
return false;
}
};