17620644768ffc235607b3a94671e49518c18686fBryan Mawhinney/*
27620644768ffc235607b3a94671e49518c18686fBryan Mawhinney * Copyright (C) 2010 ZXing authors
37620644768ffc235607b3a94671e49518c18686fBryan Mawhinney *
47620644768ffc235607b3a94671e49518c18686fBryan Mawhinney * Licensed under the Apache License, Version 2.0 (the "License");
57620644768ffc235607b3a94671e49518c18686fBryan Mawhinney * you may not use this file except in compliance with the License.
67620644768ffc235607b3a94671e49518c18686fBryan Mawhinney * You may obtain a copy of the License at
77620644768ffc235607b3a94671e49518c18686fBryan Mawhinney *
87620644768ffc235607b3a94671e49518c18686fBryan Mawhinney *      http://www.apache.org/licenses/LICENSE-2.0
97620644768ffc235607b3a94671e49518c18686fBryan Mawhinney *
107620644768ffc235607b3a94671e49518c18686fBryan Mawhinney * Unless required by applicable law or agreed to in writing, software
117620644768ffc235607b3a94671e49518c18686fBryan Mawhinney * distributed under the License is distributed on an "AS IS" BASIS,
127620644768ffc235607b3a94671e49518c18686fBryan Mawhinney * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
137620644768ffc235607b3a94671e49518c18686fBryan Mawhinney * See the License for the specific language governing permissions and
147620644768ffc235607b3a94671e49518c18686fBryan Mawhinney * limitations under the License.
157620644768ffc235607b3a94671e49518c18686fBryan Mawhinney */
167620644768ffc235607b3a94671e49518c18686fBryan Mawhinney
177620644768ffc235607b3a94671e49518c18686fBryan Mawhinneypackage com.google.zxing.client.android.camera;
187620644768ffc235607b3a94671e49518c18686fBryan Mawhinney
197620644768ffc235607b3a94671e49518c18686fBryan Mawhinneyimport android.content.Context;
207620644768ffc235607b3a94671e49518c18686fBryan Mawhinneyimport android.content.SharedPreferences;
217620644768ffc235607b3a94671e49518c18686fBryan Mawhinneyimport android.graphics.Point;
227620644768ffc235607b3a94671e49518c18686fBryan Mawhinneyimport android.hardware.Camera;
237620644768ffc235607b3a94671e49518c18686fBryan Mawhinneyimport android.preference.PreferenceManager;
247620644768ffc235607b3a94671e49518c18686fBryan Mawhinneyimport android.util.Log;
257620644768ffc235607b3a94671e49518c18686fBryan Mawhinneyimport android.view.Display;
267620644768ffc235607b3a94671e49518c18686fBryan Mawhinneyimport android.view.WindowManager;
277620644768ffc235607b3a94671e49518c18686fBryan Mawhinney
287620644768ffc235607b3a94671e49518c18686fBryan Mawhinneyimport java.util.Collection;
297620644768ffc235607b3a94671e49518c18686fBryan Mawhinney
307620644768ffc235607b3a94671e49518c18686fBryan Mawhinney/**
317620644768ffc235607b3a94671e49518c18686fBryan Mawhinney * A class which deals with reading, parsing, and setting the camera parameters which are used to
327620644768ffc235607b3a94671e49518c18686fBryan Mawhinney * configure the camera hardware.
337620644768ffc235607b3a94671e49518c18686fBryan Mawhinney */
347620644768ffc235607b3a94671e49518c18686fBryan Mawhinneyfinal class CameraConfigurationManager {
357620644768ffc235607b3a94671e49518c18686fBryan Mawhinney
367620644768ffc235607b3a94671e49518c18686fBryan Mawhinney  private static final String TAG = "CameraConfiguration";
377620644768ffc235607b3a94671e49518c18686fBryan Mawhinney  private static final int MIN_PREVIEW_PIXELS = 320 * 240; // small screen
387620644768ffc235607b3a94671e49518c18686fBryan Mawhinney  private static final int MAX_PREVIEW_PIXELS = 800 * 480; // large/HD screen
397620644768ffc235607b3a94671e49518c18686fBryan Mawhinney
407620644768ffc235607b3a94671e49518c18686fBryan Mawhinney  private final Context context;
417620644768ffc235607b3a94671e49518c18686fBryan Mawhinney  private Point screenResolution;
427620644768ffc235607b3a94671e49518c18686fBryan Mawhinney  private Point cameraResolution;
437620644768ffc235607b3a94671e49518c18686fBryan Mawhinney
447620644768ffc235607b3a94671e49518c18686fBryan Mawhinney  CameraConfigurationManager(Context context) {
457620644768ffc235607b3a94671e49518c18686fBryan Mawhinney    this.context = context;
467620644768ffc235607b3a94671e49518c18686fBryan Mawhinney  }
477620644768ffc235607b3a94671e49518c18686fBryan Mawhinney
487620644768ffc235607b3a94671e49518c18686fBryan Mawhinney  /**
497620644768ffc235607b3a94671e49518c18686fBryan Mawhinney   * Reads, one time, values from the camera that are needed by the app.
507620644768ffc235607b3a94671e49518c18686fBryan Mawhinney   */
517620644768ffc235607b3a94671e49518c18686fBryan Mawhinney  void initFromCameraParameters(Camera camera) {
527620644768ffc235607b3a94671e49518c18686fBryan Mawhinney    Camera.Parameters parameters = camera.getParameters();
537620644768ffc235607b3a94671e49518c18686fBryan Mawhinney    WindowManager manager = (WindowManager) context.getSystemService(Context.WINDOW_SERVICE);
547620644768ffc235607b3a94671e49518c18686fBryan Mawhinney    Display display = manager.getDefaultDisplay();
557620644768ffc235607b3a94671e49518c18686fBryan Mawhinney    int width = display.getWidth();
567620644768ffc235607b3a94671e49518c18686fBryan Mawhinney    int height = display.getHeight();
577620644768ffc235607b3a94671e49518c18686fBryan Mawhinney    // We're landscape-only, and have apparently seen issues with display thinking it's portrait
587620644768ffc235607b3a94671e49518c18686fBryan Mawhinney    // when waking from sleep. If it's not landscape, assume it's mistaken and reverse them:
597620644768ffc235607b3a94671e49518c18686fBryan Mawhinney    if (width < height) {
607620644768ffc235607b3a94671e49518c18686fBryan Mawhinney      Log.i(TAG, "Display reports portrait orientation; assuming this is incorrect");
617620644768ffc235607b3a94671e49518c18686fBryan Mawhinney      int temp = width;
627620644768ffc235607b3a94671e49518c18686fBryan Mawhinney      width = height;
637620644768ffc235607b3a94671e49518c18686fBryan Mawhinney      height = temp;
647620644768ffc235607b3a94671e49518c18686fBryan Mawhinney    }
657620644768ffc235607b3a94671e49518c18686fBryan Mawhinney    screenResolution = new Point(width, height);
667620644768ffc235607b3a94671e49518c18686fBryan Mawhinney    Log.i(TAG, "Screen resolution: " + screenResolution);
677620644768ffc235607b3a94671e49518c18686fBryan Mawhinney    cameraResolution = findBestPreviewSizeValue(parameters, screenResolution, false);
687620644768ffc235607b3a94671e49518c18686fBryan Mawhinney    Log.i(TAG, "Camera resolution: " + cameraResolution);
697620644768ffc235607b3a94671e49518c18686fBryan Mawhinney  }
707620644768ffc235607b3a94671e49518c18686fBryan Mawhinney
717620644768ffc235607b3a94671e49518c18686fBryan Mawhinney  void setDesiredCameraParameters(Camera camera) {
727620644768ffc235607b3a94671e49518c18686fBryan Mawhinney    Camera.Parameters parameters = camera.getParameters();
737620644768ffc235607b3a94671e49518c18686fBryan Mawhinney
747620644768ffc235607b3a94671e49518c18686fBryan Mawhinney    if (parameters == null) {
757620644768ffc235607b3a94671e49518c18686fBryan Mawhinney      Log.w(TAG, "Device error: no camera parameters are available. Proceeding without configuration.");
767620644768ffc235607b3a94671e49518c18686fBryan Mawhinney      return;
777620644768ffc235607b3a94671e49518c18686fBryan Mawhinney    }
787620644768ffc235607b3a94671e49518c18686fBryan Mawhinney
797620644768ffc235607b3a94671e49518c18686fBryan Mawhinney    SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(context);
807620644768ffc235607b3a94671e49518c18686fBryan Mawhinney
817620644768ffc235607b3a94671e49518c18686fBryan Mawhinney    initializeTorch(parameters, prefs);
827620644768ffc235607b3a94671e49518c18686fBryan Mawhinney    String focusMode = findSettableValue(parameters.getSupportedFocusModes(),
837620644768ffc235607b3a94671e49518c18686fBryan Mawhinney                                         Camera.Parameters.FOCUS_MODE_AUTO,
847620644768ffc235607b3a94671e49518c18686fBryan Mawhinney                                         Camera.Parameters.FOCUS_MODE_MACRO);
857620644768ffc235607b3a94671e49518c18686fBryan Mawhinney    if (focusMode != null) {
867620644768ffc235607b3a94671e49518c18686fBryan Mawhinney      parameters.setFocusMode(focusMode);
877620644768ffc235607b3a94671e49518c18686fBryan Mawhinney    }
887620644768ffc235607b3a94671e49518c18686fBryan Mawhinney
897620644768ffc235607b3a94671e49518c18686fBryan Mawhinney    parameters.setPreviewSize(cameraResolution.x, cameraResolution.y);
907620644768ffc235607b3a94671e49518c18686fBryan Mawhinney    camera.setParameters(parameters);
917620644768ffc235607b3a94671e49518c18686fBryan Mawhinney  }
927620644768ffc235607b3a94671e49518c18686fBryan Mawhinney
937620644768ffc235607b3a94671e49518c18686fBryan Mawhinney  Point getCameraResolution() {
947620644768ffc235607b3a94671e49518c18686fBryan Mawhinney    return cameraResolution;
957620644768ffc235607b3a94671e49518c18686fBryan Mawhinney  }
967620644768ffc235607b3a94671e49518c18686fBryan Mawhinney
977620644768ffc235607b3a94671e49518c18686fBryan Mawhinney  Point getScreenResolution() {
987620644768ffc235607b3a94671e49518c18686fBryan Mawhinney    return screenResolution;
997620644768ffc235607b3a94671e49518c18686fBryan Mawhinney  }
1007620644768ffc235607b3a94671e49518c18686fBryan Mawhinney
1017620644768ffc235607b3a94671e49518c18686fBryan Mawhinney  void setTorch(Camera camera, boolean newSetting) {
1027620644768ffc235607b3a94671e49518c18686fBryan Mawhinney    Camera.Parameters parameters = camera.getParameters();
1037620644768ffc235607b3a94671e49518c18686fBryan Mawhinney    doSetTorch(parameters, newSetting);
1047620644768ffc235607b3a94671e49518c18686fBryan Mawhinney    camera.setParameters(parameters);
1057620644768ffc235607b3a94671e49518c18686fBryan Mawhinney    SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(context);
1067620644768ffc235607b3a94671e49518c18686fBryan Mawhinney    boolean currentSetting = false; // prefs.getBoolean(PreferencesActivity.KEY_FRONT_LIGHT, false);
1077620644768ffc235607b3a94671e49518c18686fBryan Mawhinney//    if (currentSetting != newSetting) {
1087620644768ffc235607b3a94671e49518c18686fBryan Mawhinney//      SharedPreferences.Editor editor = prefs.edit();
1097620644768ffc235607b3a94671e49518c18686fBryan Mawhinney//      editor.putBoolean(PreferencesActivity.KEY_FRONT_LIGHT, newSetting);
1107620644768ffc235607b3a94671e49518c18686fBryan Mawhinney//      editor.commit();
1117620644768ffc235607b3a94671e49518c18686fBryan Mawhinney//    }
1127620644768ffc235607b3a94671e49518c18686fBryan Mawhinney  }
1137620644768ffc235607b3a94671e49518c18686fBryan Mawhinney
1147620644768ffc235607b3a94671e49518c18686fBryan Mawhinney  private static void initializeTorch(Camera.Parameters parameters, SharedPreferences prefs) {
1157620644768ffc235607b3a94671e49518c18686fBryan Mawhinney    boolean currentSetting = false;// prefs.getBoolean(PreferencesActivity.KEY_FRONT_LIGHT, false);
1167620644768ffc235607b3a94671e49518c18686fBryan Mawhinney    doSetTorch(parameters, currentSetting);
1177620644768ffc235607b3a94671e49518c18686fBryan Mawhinney  }
1187620644768ffc235607b3a94671e49518c18686fBryan Mawhinney
1197620644768ffc235607b3a94671e49518c18686fBryan Mawhinney  private static void doSetTorch(Camera.Parameters parameters, boolean newSetting) {
1207620644768ffc235607b3a94671e49518c18686fBryan Mawhinney    String flashMode;
1217620644768ffc235607b3a94671e49518c18686fBryan Mawhinney    if (newSetting) {
1227620644768ffc235607b3a94671e49518c18686fBryan Mawhinney      flashMode = findSettableValue(parameters.getSupportedFlashModes(),
1237620644768ffc235607b3a94671e49518c18686fBryan Mawhinney                                    Camera.Parameters.FLASH_MODE_TORCH,
1247620644768ffc235607b3a94671e49518c18686fBryan Mawhinney                                    Camera.Parameters.FLASH_MODE_ON);
1257620644768ffc235607b3a94671e49518c18686fBryan Mawhinney    } else {
1267620644768ffc235607b3a94671e49518c18686fBryan Mawhinney      flashMode = findSettableValue(parameters.getSupportedFlashModes(),
1277620644768ffc235607b3a94671e49518c18686fBryan Mawhinney                                    Camera.Parameters.FLASH_MODE_OFF);
1287620644768ffc235607b3a94671e49518c18686fBryan Mawhinney    }
1297620644768ffc235607b3a94671e49518c18686fBryan Mawhinney    if (flashMode != null) {
1307620644768ffc235607b3a94671e49518c18686fBryan Mawhinney      parameters.setFlashMode(flashMode);
1317620644768ffc235607b3a94671e49518c18686fBryan Mawhinney    }
1327620644768ffc235607b3a94671e49518c18686fBryan Mawhinney  }
1337620644768ffc235607b3a94671e49518c18686fBryan Mawhinney
1347620644768ffc235607b3a94671e49518c18686fBryan Mawhinney  private static Point findBestPreviewSizeValue(Camera.Parameters parameters,
1357620644768ffc235607b3a94671e49518c18686fBryan Mawhinney                                                Point screenResolution,
1367620644768ffc235607b3a94671e49518c18686fBryan Mawhinney                                                boolean portrait) {
1377620644768ffc235607b3a94671e49518c18686fBryan Mawhinney    Point bestSize = null;
1387620644768ffc235607b3a94671e49518c18686fBryan Mawhinney    int diff = Integer.MAX_VALUE;
1397620644768ffc235607b3a94671e49518c18686fBryan Mawhinney    for (Camera.Size supportedPreviewSize : parameters.getSupportedPreviewSizes()) {
1407620644768ffc235607b3a94671e49518c18686fBryan Mawhinney      int pixels = supportedPreviewSize.height * supportedPreviewSize.width;
1417620644768ffc235607b3a94671e49518c18686fBryan Mawhinney      if (pixels < MIN_PREVIEW_PIXELS || pixels > MAX_PREVIEW_PIXELS) {
1427620644768ffc235607b3a94671e49518c18686fBryan Mawhinney        continue;
1437620644768ffc235607b3a94671e49518c18686fBryan Mawhinney      }
1447620644768ffc235607b3a94671e49518c18686fBryan Mawhinney      int supportedWidth = portrait ? supportedPreviewSize.height : supportedPreviewSize.width;
1457620644768ffc235607b3a94671e49518c18686fBryan Mawhinney      int supportedHeight = portrait ? supportedPreviewSize.width : supportedPreviewSize.height;
1467620644768ffc235607b3a94671e49518c18686fBryan Mawhinney      int newDiff = Math.abs(screenResolution.x * supportedHeight - supportedWidth * screenResolution.y);
1477620644768ffc235607b3a94671e49518c18686fBryan Mawhinney      if (newDiff == 0) {
1487620644768ffc235607b3a94671e49518c18686fBryan Mawhinney        bestSize = new Point(supportedWidth, supportedHeight);
1497620644768ffc235607b3a94671e49518c18686fBryan Mawhinney        break;
1507620644768ffc235607b3a94671e49518c18686fBryan Mawhinney      }
1517620644768ffc235607b3a94671e49518c18686fBryan Mawhinney      if (newDiff < diff) {
1527620644768ffc235607b3a94671e49518c18686fBryan Mawhinney        bestSize = new Point(supportedWidth, supportedHeight);
1537620644768ffc235607b3a94671e49518c18686fBryan Mawhinney        diff = newDiff;
1547620644768ffc235607b3a94671e49518c18686fBryan Mawhinney      }
1557620644768ffc235607b3a94671e49518c18686fBryan Mawhinney    }
1567620644768ffc235607b3a94671e49518c18686fBryan Mawhinney    if (bestSize == null) {
1577620644768ffc235607b3a94671e49518c18686fBryan Mawhinney      Camera.Size defaultSize = parameters.getPreviewSize();
1587620644768ffc235607b3a94671e49518c18686fBryan Mawhinney      bestSize = new Point(defaultSize.width, defaultSize.height);
1597620644768ffc235607b3a94671e49518c18686fBryan Mawhinney    }
1607620644768ffc235607b3a94671e49518c18686fBryan Mawhinney    return bestSize;
1617620644768ffc235607b3a94671e49518c18686fBryan Mawhinney  }
1627620644768ffc235607b3a94671e49518c18686fBryan Mawhinney
1637620644768ffc235607b3a94671e49518c18686fBryan Mawhinney  private static String findSettableValue(Collection<String> supportedValues,
1647620644768ffc235607b3a94671e49518c18686fBryan Mawhinney                                          String... desiredValues) {
1657620644768ffc235607b3a94671e49518c18686fBryan Mawhinney    Log.i(TAG, "Supported values: " + supportedValues);
1667620644768ffc235607b3a94671e49518c18686fBryan Mawhinney    String result = null;
1677620644768ffc235607b3a94671e49518c18686fBryan Mawhinney    if (supportedValues != null) {
1687620644768ffc235607b3a94671e49518c18686fBryan Mawhinney      for (String desiredValue : desiredValues) {
1697620644768ffc235607b3a94671e49518c18686fBryan Mawhinney        if (supportedValues.contains(desiredValue)) {
1707620644768ffc235607b3a94671e49518c18686fBryan Mawhinney          result = desiredValue;
1717620644768ffc235607b3a94671e49518c18686fBryan Mawhinney          break;
1727620644768ffc235607b3a94671e49518c18686fBryan Mawhinney        }
1737620644768ffc235607b3a94671e49518c18686fBryan Mawhinney      }
1747620644768ffc235607b3a94671e49518c18686fBryan Mawhinney    }
1757620644768ffc235607b3a94671e49518c18686fBryan Mawhinney    Log.i(TAG, "Settable value: " + result);
1767620644768ffc235607b3a94671e49518c18686fBryan Mawhinney    return result;
1777620644768ffc235607b3a94671e49518c18686fBryan Mawhinney  }
1787620644768ffc235607b3a94671e49518c18686fBryan Mawhinney
1797620644768ffc235607b3a94671e49518c18686fBryan Mawhinney}
180