/* * 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 mGeneralSetting = new TreeMap<>(); protected final List mMeteringAreas = new ArrayList<>(); protected final List 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. *

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.

*/ 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}. * *

Setting {@code processingMethod} to {@code null} means that * {@code latitude}, {@code longitude}, and {@code altitude} will be * completely ignored.

*/ 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 areas) { mMeteringAreas.clear(); if (areas != null) { mMeteringAreas.addAll(areas); } } public List getMeteringAreas() { return new ArrayList(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 areas) { mFocusAreas.clear(); if (areas != null) { mFocusAreas.addAll(areas); } } public List getFocusAreas() { return new ArrayList(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); } }