1 /* 2 * Copyright (C) 2014 The Android Open Source Project 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 17 package com.android.ex.camera2.portability; 18 19 import android.hardware.Camera; 20 21 import com.android.ex.camera2.portability.debug.Log; 22 23 import java.util.ArrayList; 24 import java.util.List; 25 import java.util.Map; 26 import java.util.TreeMap; 27 28 /** 29 * A class which stores the camera settings. 30 */ 31 public abstract class CameraSettings { 32 private static final Log.Tag TAG = new Log.Tag("CamSet"); 33 34 // Attempts to provide a value outside this range will be ignored. 35 private static final int MIN_JPEG_COMPRESSION_QUALITY = 1; 36 private static final int MAX_JPEG_COMPRESSION_QUALITY = 100; 37 38 protected final Map<String, String> mGeneralSetting = new TreeMap<>(); 39 protected final List<Camera.Area> mMeteringAreas = new ArrayList<>(); 40 protected final List<Camera.Area> mFocusAreas = new ArrayList<>(); 41 protected boolean mSizesLocked; 42 protected int mPreviewFpsRangeMin; 43 protected int mPreviewFpsRangeMax; 44 protected int mPreviewFrameRate; 45 protected Size mCurrentPreviewSize; 46 private int mCurrentPreviewFormat; 47 protected Size mCurrentPhotoSize; 48 protected byte mJpegCompressQuality; 49 protected int mCurrentPhotoFormat; 50 protected float mCurrentZoomRatio; 51 protected int mExposureCompensationIndex; 52 protected CameraCapabilities.FlashMode mCurrentFlashMode; 53 protected CameraCapabilities.FocusMode mCurrentFocusMode; 54 protected CameraCapabilities.SceneMode mCurrentSceneMode; 55 protected CameraCapabilities.WhiteBalance mWhiteBalance; 56 protected boolean mVideoStabilizationEnabled; 57 protected boolean mAutoExposureLocked; 58 protected boolean mAutoWhiteBalanceLocked; 59 protected boolean mRecordingHintEnabled; 60 protected GpsData mGpsData; 61 protected Size mExifThumbnailSize; 62 63 /** 64 * An immutable class storing GPS related information. 65 * <p>It's a hack since we always use GPS time stamp but does not use other 66 * fields sometimes. Setting processing method to null means the other 67 * fields should not be used.</p> 68 */ 69 public static class GpsData { 70 public final double latitude; 71 public final double longitude; 72 public final double altitude; 73 public final long timeStamp; 74 public final String processingMethod; 75 76 /** 77 * Construct what may or may not actually represent a location, 78 * depending on the value of {@code processingMethod}. 79 * 80 * <p>Setting {@code processingMethod} to {@code null} means that 81 * {@code latitude}, {@code longitude}, and {@code altitude} will be 82 * completely ignored.</p> 83 */ 84 public GpsData(double latitude, double longitude, double altitude, long timeStamp, 85 String processingMethod) { 86 if (processingMethod == null && 87 (latitude != 0.0 || longitude != 0.0 || altitude != 0.0)) { 88 Log.w(TAG, "GpsData's nonzero data will be ignored due to null processingMethod"); 89 } 90 this.latitude = latitude; 91 this.longitude = longitude; 92 this.altitude = altitude; 93 this.timeStamp = timeStamp; 94 this.processingMethod = processingMethod; 95 } 96 97 /** Copy constructor. */ 98 public GpsData(GpsData src) { 99 this.latitude = src.latitude; 100 this.longitude = src.longitude; 101 this.altitude = src.altitude; 102 this.timeStamp = src.timeStamp; 103 this.processingMethod = src.processingMethod; 104 } 105 } 106 107 protected CameraSettings() { 108 } 109 110 /** 111 * Copy constructor. 112 * 113 * @param src The source settings. 114 * @return The copy of the source. 115 */ 116 protected CameraSettings(CameraSettings src) { 117 mGeneralSetting.putAll(src.mGeneralSetting); 118 mMeteringAreas.addAll(src.mMeteringAreas); 119 mFocusAreas.addAll(src.mFocusAreas); 120 mSizesLocked = src.mSizesLocked; 121 mPreviewFpsRangeMin = src.mPreviewFpsRangeMin; 122 mPreviewFpsRangeMax = src.mPreviewFpsRangeMax; 123 mPreviewFrameRate = src.mPreviewFrameRate; 124 mCurrentPreviewSize = 125 (src.mCurrentPreviewSize == null ? null : new Size(src.mCurrentPreviewSize)); 126 mCurrentPreviewFormat = src.mCurrentPreviewFormat; 127 mCurrentPhotoSize = 128 (src.mCurrentPhotoSize == null ? null : new Size(src.mCurrentPhotoSize)); 129 mJpegCompressQuality = src.mJpegCompressQuality; 130 mCurrentPhotoFormat = src.mCurrentPhotoFormat; 131 mCurrentZoomRatio = src.mCurrentZoomRatio; 132 mExposureCompensationIndex = src.mExposureCompensationIndex; 133 mCurrentFlashMode = src.mCurrentFlashMode; 134 mCurrentFocusMode = src.mCurrentFocusMode; 135 mCurrentSceneMode = src.mCurrentSceneMode; 136 mWhiteBalance = src.mWhiteBalance; 137 mVideoStabilizationEnabled = src.mVideoStabilizationEnabled; 138 mAutoExposureLocked = src.mAutoExposureLocked; 139 mAutoWhiteBalanceLocked = src.mAutoWhiteBalanceLocked; 140 mRecordingHintEnabled = src.mRecordingHintEnabled; 141 mGpsData = src.mGpsData; 142 mExifThumbnailSize = src.mExifThumbnailSize; 143 } 144 145 /** 146 * @return A copy of this object, as an instance of the implementing class. 147 */ 148 public abstract CameraSettings copy(); 149 150 /** General setting **/ 151 @Deprecated 152 public void setSetting(String key, String value) { 153 mGeneralSetting.put(key, value); 154 } 155 156 /** 157 * Changes whether classes outside this class are allowed to set the preview 158 * and photo capture sizes. 159 * 160 * @param locked Whether to prevent changes to these fields. 161 * 162 * @see #setPhotoSize 163 * @see #setPreviewSize 164 */ 165 /*package*/ void setSizesLocked(boolean locked) { 166 mSizesLocked = locked; 167 } 168 169 /** Preview **/ 170 171 /** 172 * Sets the preview FPS range. This call will invalidate prior calls to 173 * {@link #setPreviewFrameRate(int)}. 174 * 175 * @param min The min FPS. 176 * @param max The max FPS. 177 */ 178 public void setPreviewFpsRange(int min, int max) { 179 if (min > max) { 180 int temp = max; 181 max = min; 182 min = temp; 183 } 184 mPreviewFpsRangeMax = max; 185 mPreviewFpsRangeMin = min; 186 mPreviewFrameRate = -1; 187 } 188 189 /** 190 * @return The min of the preview FPS range. 191 */ 192 public int getPreviewFpsRangeMin() { 193 return mPreviewFpsRangeMin; 194 } 195 196 /** 197 * @return The max of the preview FPS range. 198 */ 199 public int getPreviewFpsRangeMax() { 200 return mPreviewFpsRangeMax; 201 } 202 203 /** 204 * Sets the preview FPS. This call will invalidate prior calls to 205 * {@link #setPreviewFpsRange(int, int)}. 206 * 207 * @param frameRate The target frame rate. 208 */ 209 public void setPreviewFrameRate(int frameRate) { 210 if (frameRate > 0) { 211 mPreviewFrameRate = frameRate; 212 mPreviewFpsRangeMax = frameRate; 213 mPreviewFpsRangeMin = frameRate; 214 } 215 } 216 217 public int getPreviewFrameRate() { 218 return mPreviewFrameRate; 219 } 220 221 /** 222 * @return The current preview size. 223 */ 224 public Size getCurrentPreviewSize() { 225 return new Size(mCurrentPreviewSize); 226 } 227 228 /** 229 * @param previewSize The size to use for preview. 230 * @return Whether the operation was allowed (i.e. the sizes are unlocked). 231 */ 232 public boolean setPreviewSize(Size previewSize) { 233 if (mSizesLocked) { 234 Log.w(TAG, "Attempt to change preview size while locked"); 235 return false; 236 } 237 238 mCurrentPreviewSize = new Size(previewSize); 239 return true; 240 } 241 242 /** 243 * Sets the preview format. 244 * 245 * @param format 246 * @see {@link android.graphics.ImageFormat}. 247 */ 248 public void setPreviewFormat(int format) { 249 mCurrentPreviewFormat = format; 250 } 251 252 /** 253 * @return The preview format. 254 * @see {@link android.graphics.ImageFormat}. 255 */ 256 public int getCurrentPreviewFormat() { 257 return mCurrentPreviewFormat; 258 } 259 260 /** Picture **/ 261 262 /** 263 * @return The current photo size. 264 */ 265 public Size getCurrentPhotoSize() { 266 return new Size(mCurrentPhotoSize); 267 } 268 269 /** 270 * @param photoSize The size to use for preview. 271 * @return Whether the operation was allowed (i.e. the sizes are unlocked). 272 */ 273 public boolean setPhotoSize(Size photoSize) { 274 if (mSizesLocked) { 275 Log.w(TAG, "Attempt to change photo size while locked"); 276 return false; 277 } 278 279 mCurrentPhotoSize = new Size(photoSize); 280 return true; 281 } 282 283 /** 284 * Sets the format for the photo. 285 * 286 * @param format The format for the photos taken. 287 * @see {@link android.graphics.ImageFormat}. 288 */ 289 public void setPhotoFormat(int format) { 290 mCurrentPhotoFormat = format; 291 } 292 293 /** 294 * @return The format for the photos taken. 295 * @see {@link android.graphics.ImageFormat}. 296 */ 297 public int getCurrentPhotoFormat() { 298 return mCurrentPhotoFormat; 299 } 300 301 /** 302 * Sets the JPEG compression quality. 303 * 304 * @param quality The quality for JPEG. 305 */ 306 public void setPhotoJpegCompressionQuality(int quality) { 307 if (quality < MIN_JPEG_COMPRESSION_QUALITY || quality > MAX_JPEG_COMPRESSION_QUALITY) { 308 Log.w(TAG, "Ignoring JPEG quality that falls outside the expected range"); 309 return; 310 } 311 // This is safe because the positive numbers go up to 127. 312 mJpegCompressQuality = (byte) quality; 313 } 314 315 public int getPhotoJpegCompressionQuality() { 316 return mJpegCompressQuality; 317 } 318 319 /** Zoom **/ 320 321 /** 322 * @return The current zoom ratio. The min is 1.0f. 323 */ 324 public float getCurrentZoomRatio() { 325 return mCurrentZoomRatio; 326 } 327 328 /** 329 * Sets the zoom ratio. 330 * @param ratio The new zoom ratio. Should be in the range between 1.0 to 331 * the value returned from {@link 332 * com.android.camera.cameradevice.CameraCapabilities#getMaxZoomRatio()}. 333 * @throws java.lang.UnsupportedOperationException if the ratio is not 334 * supported. 335 */ 336 public void setZoomRatio(float ratio) { 337 mCurrentZoomRatio = ratio; 338 } 339 340 /** Exposure **/ 341 342 public void setExposureCompensationIndex(int index) { 343 mExposureCompensationIndex = index; 344 } 345 346 /** 347 * @return The exposure compensation, with 0 meaning unadjusted. 348 */ 349 public int getExposureCompensationIndex() { 350 return mExposureCompensationIndex; 351 } 352 353 public void setAutoExposureLock(boolean locked) { 354 mAutoExposureLocked = locked; 355 } 356 357 public boolean isAutoExposureLocked() { 358 return mAutoExposureLocked; 359 } 360 361 /** 362 * @param areas The areas for autoexposure. The coordinate system has domain 363 * and range [-1000,1000], measured relative to the visible 364 * preview image, with orientation matching that of the sensor. 365 * This means the coordinates must be transformed to account 366 * for the devices rotation---but not the zoom level---before 367 * being passed into this method. 368 */ 369 public void setMeteringAreas(List<Camera.Area> areas) { 370 mMeteringAreas.clear(); 371 if (areas != null) { 372 mMeteringAreas.addAll(areas); 373 } 374 } 375 376 public List<Camera.Area> getMeteringAreas() { 377 return new ArrayList<Camera.Area>(mMeteringAreas); 378 } 379 380 /** Flash **/ 381 382 public CameraCapabilities.FlashMode getCurrentFlashMode() { 383 return mCurrentFlashMode; 384 } 385 386 public void setFlashMode(CameraCapabilities.FlashMode flashMode) { 387 mCurrentFlashMode = flashMode; 388 } 389 390 /** Focus **/ 391 392 /** 393 * Sets the focus mode. 394 * @param focusMode The focus mode to use. 395 */ 396 public void setFocusMode(CameraCapabilities.FocusMode focusMode) { 397 mCurrentFocusMode = focusMode; 398 } 399 400 /** 401 * @return The current focus mode. 402 */ 403 public CameraCapabilities.FocusMode getCurrentFocusMode() { 404 return mCurrentFocusMode; 405 } 406 407 /** 408 * @param areas The areas to focus. The coordinate system has domain and 409 * range [-1000,1000], measured relative to the visible preview 410 * image, with orientation matching that of the sensor. This 411 * means the coordinates must be transformed to account for 412 * the devices rotation---but not the zoom level---before being 413 * passed into this method. 414 */ 415 public void setFocusAreas(List<Camera.Area> areas) { 416 mFocusAreas.clear(); 417 if (areas != null) { 418 mFocusAreas.addAll(areas); 419 } 420 } 421 422 public List<Camera.Area> getFocusAreas() { 423 return new ArrayList<Camera.Area>(mFocusAreas); 424 } 425 426 /** White balance **/ 427 428 public void setWhiteBalance(CameraCapabilities.WhiteBalance whiteBalance) { 429 mWhiteBalance = whiteBalance; 430 } 431 432 public CameraCapabilities.WhiteBalance getWhiteBalance() { 433 return mWhiteBalance; 434 } 435 436 public void setAutoWhiteBalanceLock(boolean locked) { 437 mAutoWhiteBalanceLocked = locked; 438 } 439 440 public boolean isAutoWhiteBalanceLocked() { 441 return mAutoWhiteBalanceLocked; 442 } 443 444 /** Scene mode **/ 445 446 /** 447 * @return The current scene mode. 448 */ 449 public CameraCapabilities.SceneMode getCurrentSceneMode() { 450 return mCurrentSceneMode; 451 } 452 453 /** 454 * Sets the scene mode for capturing. 455 * 456 * @param sceneMode The scene mode to use. 457 * @throws java.lang.UnsupportedOperationException if it's not supported. 458 */ 459 public void setSceneMode(CameraCapabilities.SceneMode sceneMode) { 460 mCurrentSceneMode = sceneMode; 461 } 462 463 /** Other Features **/ 464 465 public void setVideoStabilization(boolean enabled) { 466 mVideoStabilizationEnabled = enabled; 467 } 468 469 public boolean isVideoStabilizationEnabled() { 470 return mVideoStabilizationEnabled; 471 } 472 473 public void setRecordingHintEnabled(boolean hintEnabled) { 474 mRecordingHintEnabled = hintEnabled; 475 } 476 477 public boolean isRecordingHintEnabled() { 478 return mRecordingHintEnabled; 479 } 480 481 public void setGpsData(GpsData data) { 482 mGpsData = new GpsData(data); 483 } 484 485 public GpsData getGpsData() { 486 return (mGpsData == null ? null : new GpsData(mGpsData)); 487 } 488 489 public void clearGpsData() { 490 mGpsData = null; 491 } 492 493 /** 494 * Sets the size of the thumbnail in EXIF header. To suppress thumbnail 495 * generation, set a size of (0,0). 496 * 497 * @param s The size for the thumbnail. If {@code null}, agent will not 498 * set a thumbnail size. 499 */ 500 public void setExifThumbnailSize(Size s) { 501 mExifThumbnailSize = s; 502 } 503 504 /** 505 * Gets the size of the thumbnail in EXIF header. 506 * 507 * @return desired thumbnail size, or null if no size was set 508 */ 509 public Size getExifThumbnailSize() { 510 return (mExifThumbnailSize == null) ? null : new Size(mExifThumbnailSize); 511 } 512 } 513