/*
|
* Copyright (C) 2014 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.ex.camera2.portability;
|
|
import android.hardware.Camera;
|
|
import com.android.ex.camera2.portability.debug.Log;
|
|
import java.util.ArrayList;
|
import java.util.List;
|
import java.util.Map;
|
import java.util.TreeMap;
|
|
/**
|
* A class which stores the camera settings.
|
*/
|
public abstract class CameraSettings {
|
private static final Log.Tag TAG = new Log.Tag("CamSet");
|
|
// Attempts to provide a value outside this range will be ignored.
|
private static final int MIN_JPEG_COMPRESSION_QUALITY = 1;
|
private static final int MAX_JPEG_COMPRESSION_QUALITY = 100;
|
|
protected final Map<String, String> mGeneralSetting = new TreeMap<>();
|
protected final List<Camera.Area> mMeteringAreas = new ArrayList<>();
|
protected final List<Camera.Area> mFocusAreas = new ArrayList<>();
|
protected boolean mSizesLocked;
|
protected int mPreviewFpsRangeMin;
|
protected int mPreviewFpsRangeMax;
|
protected int mPreviewFrameRate;
|
protected Size mCurrentPreviewSize;
|
private int mCurrentPreviewFormat;
|
protected Size mCurrentPhotoSize;
|
protected byte mJpegCompressQuality;
|
protected int mCurrentPhotoFormat;
|
protected float mCurrentZoomRatio;
|
protected int mExposureCompensationIndex;
|
protected CameraCapabilities.FlashMode mCurrentFlashMode;
|
protected CameraCapabilities.FocusMode mCurrentFocusMode;
|
protected CameraCapabilities.SceneMode mCurrentSceneMode;
|
protected CameraCapabilities.WhiteBalance mWhiteBalance;
|
protected boolean mVideoStabilizationEnabled;
|
protected boolean mAutoExposureLocked;
|
protected boolean mAutoWhiteBalanceLocked;
|
protected boolean mRecordingHintEnabled;
|
protected GpsData mGpsData;
|
protected Size mExifThumbnailSize;
|
|
/**
|
* An immutable class storing GPS related information.
|
* <p>It's a hack since we always use GPS time stamp but does not use other
|
* fields sometimes. Setting processing method to null means the other
|
* fields should not be used.</p>
|
*/
|
public static class GpsData {
|
public final double latitude;
|
public final double longitude;
|
public final double altitude;
|
public final long timeStamp;
|
public final String processingMethod;
|
|
/**
|
* Construct what may or may not actually represent a location,
|
* depending on the value of {@code processingMethod}.
|
*
|
* <p>Setting {@code processingMethod} to {@code null} means that
|
* {@code latitude}, {@code longitude}, and {@code altitude} will be
|
* completely ignored.</p>
|
*/
|
public GpsData(double latitude, double longitude, double altitude, long timeStamp,
|
String processingMethod) {
|
if (processingMethod == null &&
|
(latitude != 0.0 || longitude != 0.0 || altitude != 0.0)) {
|
Log.w(TAG, "GpsData's nonzero data will be ignored due to null processingMethod");
|
}
|
this.latitude = latitude;
|
this.longitude = longitude;
|
this.altitude = altitude;
|
this.timeStamp = timeStamp;
|
this.processingMethod = processingMethod;
|
}
|
|
/** Copy constructor. */
|
public GpsData(GpsData src) {
|
this.latitude = src.latitude;
|
this.longitude = src.longitude;
|
this.altitude = src.altitude;
|
this.timeStamp = src.timeStamp;
|
this.processingMethod = src.processingMethod;
|
}
|
}
|
|
protected CameraSettings() {
|
}
|
|
/**
|
* Copy constructor.
|
*
|
* @param src The source settings.
|
* @return The copy of the source.
|
*/
|
protected CameraSettings(CameraSettings src) {
|
mGeneralSetting.putAll(src.mGeneralSetting);
|
mMeteringAreas.addAll(src.mMeteringAreas);
|
mFocusAreas.addAll(src.mFocusAreas);
|
mSizesLocked = src.mSizesLocked;
|
mPreviewFpsRangeMin = src.mPreviewFpsRangeMin;
|
mPreviewFpsRangeMax = src.mPreviewFpsRangeMax;
|
mPreviewFrameRate = src.mPreviewFrameRate;
|
mCurrentPreviewSize =
|
(src.mCurrentPreviewSize == null ? null : new Size(src.mCurrentPreviewSize));
|
mCurrentPreviewFormat = src.mCurrentPreviewFormat;
|
mCurrentPhotoSize =
|
(src.mCurrentPhotoSize == null ? null : new Size(src.mCurrentPhotoSize));
|
mJpegCompressQuality = src.mJpegCompressQuality;
|
mCurrentPhotoFormat = src.mCurrentPhotoFormat;
|
mCurrentZoomRatio = src.mCurrentZoomRatio;
|
mExposureCompensationIndex = src.mExposureCompensationIndex;
|
mCurrentFlashMode = src.mCurrentFlashMode;
|
mCurrentFocusMode = src.mCurrentFocusMode;
|
mCurrentSceneMode = src.mCurrentSceneMode;
|
mWhiteBalance = src.mWhiteBalance;
|
mVideoStabilizationEnabled = src.mVideoStabilizationEnabled;
|
mAutoExposureLocked = src.mAutoExposureLocked;
|
mAutoWhiteBalanceLocked = src.mAutoWhiteBalanceLocked;
|
mRecordingHintEnabled = src.mRecordingHintEnabled;
|
mGpsData = src.mGpsData;
|
mExifThumbnailSize = src.mExifThumbnailSize;
|
}
|
|
/**
|
* @return A copy of this object, as an instance of the implementing class.
|
*/
|
public abstract CameraSettings copy();
|
|
/** General setting **/
|
@Deprecated
|
public void setSetting(String key, String value) {
|
mGeneralSetting.put(key, value);
|
}
|
|
/**
|
* Changes whether classes outside this class are allowed to set the preview
|
* and photo capture sizes.
|
*
|
* @param locked Whether to prevent changes to these fields.
|
*
|
* @see #setPhotoSize
|
* @see #setPreviewSize
|
*/
|
/*package*/ void setSizesLocked(boolean locked) {
|
mSizesLocked = locked;
|
}
|
|
/** Preview **/
|
|
/**
|
* Sets the preview FPS range. This call will invalidate prior calls to
|
* {@link #setPreviewFrameRate(int)}.
|
*
|
* @param min The min FPS.
|
* @param max The max FPS.
|
*/
|
public void setPreviewFpsRange(int min, int max) {
|
if (min > max) {
|
int temp = max;
|
max = min;
|
min = temp;
|
}
|
mPreviewFpsRangeMax = max;
|
mPreviewFpsRangeMin = min;
|
mPreviewFrameRate = -1;
|
}
|
|
/**
|
* @return The min of the preview FPS range.
|
*/
|
public int getPreviewFpsRangeMin() {
|
return mPreviewFpsRangeMin;
|
}
|
|
/**
|
* @return The max of the preview FPS range.
|
*/
|
public int getPreviewFpsRangeMax() {
|
return mPreviewFpsRangeMax;
|
}
|
|
/**
|
* Sets the preview FPS. This call will invalidate prior calls to
|
* {@link #setPreviewFpsRange(int, int)}.
|
*
|
* @param frameRate The target frame rate.
|
*/
|
public void setPreviewFrameRate(int frameRate) {
|
if (frameRate > 0) {
|
mPreviewFrameRate = frameRate;
|
mPreviewFpsRangeMax = frameRate;
|
mPreviewFpsRangeMin = frameRate;
|
}
|
}
|
|
public int getPreviewFrameRate() {
|
return mPreviewFrameRate;
|
}
|
|
/**
|
* @return The current preview size.
|
*/
|
public Size getCurrentPreviewSize() {
|
return new Size(mCurrentPreviewSize);
|
}
|
|
/**
|
* @param previewSize The size to use for preview.
|
* @return Whether the operation was allowed (i.e. the sizes are unlocked).
|
*/
|
public boolean setPreviewSize(Size previewSize) {
|
if (mSizesLocked) {
|
Log.w(TAG, "Attempt to change preview size while locked");
|
return false;
|
}
|
|
mCurrentPreviewSize = new Size(previewSize);
|
return true;
|
}
|
|
/**
|
* Sets the preview format.
|
*
|
* @param format
|
* @see {@link android.graphics.ImageFormat}.
|
*/
|
public void setPreviewFormat(int format) {
|
mCurrentPreviewFormat = format;
|
}
|
|
/**
|
* @return The preview format.
|
* @see {@link android.graphics.ImageFormat}.
|
*/
|
public int getCurrentPreviewFormat() {
|
return mCurrentPreviewFormat;
|
}
|
|
/** Picture **/
|
|
/**
|
* @return The current photo size.
|
*/
|
public Size getCurrentPhotoSize() {
|
return new Size(mCurrentPhotoSize);
|
}
|
|
/**
|
* @param photoSize The size to use for preview.
|
* @return Whether the operation was allowed (i.e. the sizes are unlocked).
|
*/
|
public boolean setPhotoSize(Size photoSize) {
|
if (mSizesLocked) {
|
Log.w(TAG, "Attempt to change photo size while locked");
|
return false;
|
}
|
|
mCurrentPhotoSize = new Size(photoSize);
|
return true;
|
}
|
|
/**
|
* Sets the format for the photo.
|
*
|
* @param format The format for the photos taken.
|
* @see {@link android.graphics.ImageFormat}.
|
*/
|
public void setPhotoFormat(int format) {
|
mCurrentPhotoFormat = format;
|
}
|
|
/**
|
* @return The format for the photos taken.
|
* @see {@link android.graphics.ImageFormat}.
|
*/
|
public int getCurrentPhotoFormat() {
|
return mCurrentPhotoFormat;
|
}
|
|
/**
|
* Sets the JPEG compression quality.
|
*
|
* @param quality The quality for JPEG.
|
*/
|
public void setPhotoJpegCompressionQuality(int quality) {
|
if (quality < MIN_JPEG_COMPRESSION_QUALITY || quality > MAX_JPEG_COMPRESSION_QUALITY) {
|
Log.w(TAG, "Ignoring JPEG quality that falls outside the expected range");
|
return;
|
}
|
// This is safe because the positive numbers go up to 127.
|
mJpegCompressQuality = (byte) quality;
|
}
|
|
public int getPhotoJpegCompressionQuality() {
|
return mJpegCompressQuality;
|
}
|
|
/** Zoom **/
|
|
/**
|
* @return The current zoom ratio. The min is 1.0f.
|
*/
|
public float getCurrentZoomRatio() {
|
return mCurrentZoomRatio;
|
}
|
|
/**
|
* Sets the zoom ratio.
|
* @param ratio The new zoom ratio. Should be in the range between 1.0 to
|
* the value returned from {@link
|
* com.android.camera.cameradevice.CameraCapabilities#getMaxZoomRatio()}.
|
* @throws java.lang.UnsupportedOperationException if the ratio is not
|
* supported.
|
*/
|
public void setZoomRatio(float ratio) {
|
mCurrentZoomRatio = ratio;
|
}
|
|
/** Exposure **/
|
|
public void setExposureCompensationIndex(int index) {
|
mExposureCompensationIndex = index;
|
}
|
|
/**
|
* @return The exposure compensation, with 0 meaning unadjusted.
|
*/
|
public int getExposureCompensationIndex() {
|
return mExposureCompensationIndex;
|
}
|
|
public void setAutoExposureLock(boolean locked) {
|
mAutoExposureLocked = locked;
|
}
|
|
public boolean isAutoExposureLocked() {
|
return mAutoExposureLocked;
|
}
|
|
/**
|
* @param areas The areas for autoexposure. The coordinate system has domain
|
* and range [-1000,1000], measured relative to the visible
|
* preview image, with orientation matching that of the sensor.
|
* This means the coordinates must be transformed to account
|
* for the devices rotation---but not the zoom level---before
|
* being passed into this method.
|
*/
|
public void setMeteringAreas(List<Camera.Area> areas) {
|
mMeteringAreas.clear();
|
if (areas != null) {
|
mMeteringAreas.addAll(areas);
|
}
|
}
|
|
public List<Camera.Area> getMeteringAreas() {
|
return new ArrayList<Camera.Area>(mMeteringAreas);
|
}
|
|
/** Flash **/
|
|
public CameraCapabilities.FlashMode getCurrentFlashMode() {
|
return mCurrentFlashMode;
|
}
|
|
public void setFlashMode(CameraCapabilities.FlashMode flashMode) {
|
mCurrentFlashMode = flashMode;
|
}
|
|
/** Focus **/
|
|
/**
|
* Sets the focus mode.
|
* @param focusMode The focus mode to use.
|
*/
|
public void setFocusMode(CameraCapabilities.FocusMode focusMode) {
|
mCurrentFocusMode = focusMode;
|
}
|
|
/**
|
* @return The current focus mode.
|
*/
|
public CameraCapabilities.FocusMode getCurrentFocusMode() {
|
return mCurrentFocusMode;
|
}
|
|
/**
|
* @param areas The areas to focus. The coordinate system has domain and
|
* range [-1000,1000], measured relative to the visible preview
|
* image, with orientation matching that of the sensor. This
|
* means the coordinates must be transformed to account for
|
* the devices rotation---but not the zoom level---before being
|
* passed into this method.
|
*/
|
public void setFocusAreas(List<Camera.Area> areas) {
|
mFocusAreas.clear();
|
if (areas != null) {
|
mFocusAreas.addAll(areas);
|
}
|
}
|
|
public List<Camera.Area> getFocusAreas() {
|
return new ArrayList<Camera.Area>(mFocusAreas);
|
}
|
|
/** White balance **/
|
|
public void setWhiteBalance(CameraCapabilities.WhiteBalance whiteBalance) {
|
mWhiteBalance = whiteBalance;
|
}
|
|
public CameraCapabilities.WhiteBalance getWhiteBalance() {
|
return mWhiteBalance;
|
}
|
|
public void setAutoWhiteBalanceLock(boolean locked) {
|
mAutoWhiteBalanceLocked = locked;
|
}
|
|
public boolean isAutoWhiteBalanceLocked() {
|
return mAutoWhiteBalanceLocked;
|
}
|
|
/** Scene mode **/
|
|
/**
|
* @return The current scene mode.
|
*/
|
public CameraCapabilities.SceneMode getCurrentSceneMode() {
|
return mCurrentSceneMode;
|
}
|
|
/**
|
* Sets the scene mode for capturing.
|
*
|
* @param sceneMode The scene mode to use.
|
* @throws java.lang.UnsupportedOperationException if it's not supported.
|
*/
|
public void setSceneMode(CameraCapabilities.SceneMode sceneMode) {
|
mCurrentSceneMode = sceneMode;
|
}
|
|
/** Other Features **/
|
|
public void setVideoStabilization(boolean enabled) {
|
mVideoStabilizationEnabled = enabled;
|
}
|
|
public boolean isVideoStabilizationEnabled() {
|
return mVideoStabilizationEnabled;
|
}
|
|
public void setRecordingHintEnabled(boolean hintEnabled) {
|
mRecordingHintEnabled = hintEnabled;
|
}
|
|
public boolean isRecordingHintEnabled() {
|
return mRecordingHintEnabled;
|
}
|
|
public void setGpsData(GpsData data) {
|
mGpsData = new GpsData(data);
|
}
|
|
public GpsData getGpsData() {
|
return (mGpsData == null ? null : new GpsData(mGpsData));
|
}
|
|
public void clearGpsData() {
|
mGpsData = null;
|
}
|
|
/**
|
* Sets the size of the thumbnail in EXIF header. To suppress thumbnail
|
* generation, set a size of (0,0).
|
*
|
* @param s The size for the thumbnail. If {@code null}, agent will not
|
* set a thumbnail size.
|
*/
|
public void setExifThumbnailSize(Size s) {
|
mExifThumbnailSize = s;
|
}
|
|
/**
|
* Gets the size of the thumbnail in EXIF header.
|
*
|
* @return desired thumbnail size, or null if no size was set
|
*/
|
public Size getExifThumbnailSize() {
|
return (mExifThumbnailSize == null) ? null : new Size(mExifThumbnailSize);
|
}
|
}
|