content: /*
   * Copyright (C) 2010 ZXing authors
   *
   * 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.google.zxing.camera;
  
  import android.content.Context;
  import android.graphics.Point;
  import android.hardware.Camera;
  import android.os.Build;
  import android.util.Log;
  import android.view.Display;
  import android.view.WindowManager;
  
  import java.util.regex.Pattern;
  
  final class CameraConfigurationManager {
  
      private static final String TAG = CameraConfigurationManager.class.getSimpleName();
  
      private static final int TEN_DESIRED_ZOOM = 27;
      private static final int DESIRED_SHARPNESS = 30;
  
      private static final Pattern COMMA_PATTERN = Pattern.compile(",");
  
      private final Context context;
      private Point screenResolution;
      private Point cameraResolution;
      private int previewFormat;
      private String previewFormatString;
  
      CameraConfigurationManager(Context context) {
          this.context = context;
      }
  
      /**
       * Reads, one time, values from the camera that are needed by the app.
       */
      void initFromCameraParameters(Camera camera) {
          Camera.Parameters parameters = camera.getParameters();
          previewFormat = parameters.getPreviewFormat();
          previewFormatString = parameters.get("preview-format");
          Log.d(TAG, "Default preview format: " + previewFormat + '/' + previewFormatString);
          WindowManager manager = (WindowManager) context.getSystemService(Context.WINDOW_SERVICE);
          Display display = manager.getDefaultDisplay();
          screenResolution = new Point(display.getWidth(), display.getHeight());
          Log.d(TAG, "Screen resolution: " + screenResolution);
  
          //图片拉伸
          Point screenResolutionForCamera = new Point();
          screenResolutionForCamera.x = screenResolution.x;
          screenResolutionForCamera.y = screenResolution.y;
          // preview size is always something like 480*320, other 320*480
          if (screenResolution.x < screenResolution.y) {
              screenResolutionForCamera.x = screenResolution.y;
              screenResolutionForCamera.y = screenResolution.x;
          }
  
          cameraResolution = getCameraResolution(parameters, screenResolutionForCamera);
          Log.d(TAG, "Camera resolution: " + screenResolution);
  
      }
  
      /**
       * Sets the camera up to take preview images which are used for both preview and decoding.
       * We detect the preview format here so that buildLuminanceSource() can build an appropriate
       * LuminanceSource subclass. In the future we may want to force YUV420SP as it's the smallest,
       * and the planar Y can be used for barcode scanning without a copy in some cases.
       */
      void setDesiredCameraParameters(Camera camera) {
          Camera.Parameters parameters = camera.getParameters();
          Log.d(TAG, "Setting preview size: " + cameraResolution);
          parameters.setPreviewSize(cameraResolution.x, cameraResolution.y);
          setFlash(parameters);
          setZoom(parameters);
          //setSharpness(parameters);
          //modify here
          camera.setDisplayOrientation(90);
          camera.setParameters(parameters);
      }
  
      Point getCameraResolution() {
          return cameraResolution;
      }
  
      Point getScreenResolution() {
          return screenResolution;
      }
  
      int getPreviewFormat() {
          return previewFormat;
      }
  
      String getPreviewFormatString() {
          return previewFormatString;
      }
  
      private static Point getCameraResolution(Camera.Parameters parameters, Point screenResolution) {
  
          String previewSizeValueString = parameters.get("preview-size-values");
          // saw this on Xperia
          if (previewSizeValueString == null) {
              previewSizeValueString = parameters.get("preview-size-value");
          }
  
          Point cameraResolution = null;
  
          if (previewSizeValueString != null) {
              Log.d(TAG, "preview-size-values parameter: " + previewSizeValueString);
              cameraResolution = findBestPreviewSizeValue(previewSizeValueString, screenResolution);
          }
  
          if (cameraResolution == null) {
              // Ensure that the camera resolution is a multiple of 8, as the screen may not be.
              cameraResolution = new Point(
                      (screenResolution.x >> 3) << 3,
                      (screenResolution.y >> 3) << 3);
          }
  
          return cameraResolution;
      }
  
      private static Point findBestPreviewSizeValue(CharSequence previewSizeValueString, Point screenResolution) {
          int bestX = 0;
          int bestY = 0;
          int diff = Integer.MAX_VALUE;
          for (String previewSize : COMMA_PATTERN.split(previewSizeValueString)) {
  
              previewSize = previewSize.trim();
              int dimPosition = previewSize.indexOf('x');
              if (dimPosition < 0) {
                  Log.w(TAG, "Bad preview-size: " + previewSize);
                  continue;
              }
  
              int newX;
              int newY;
              try {
                  newX = Integer.parseInt(previewSize.substring(0, dimPosition));
                  newY = Integer.parseInt(previewSize.substring(dimPosition + 1));
              } catch (NumberFormatException nfe) {
                  Log.w(TAG, "Bad preview-size: " + previewSize);
                  continue;
              }
  
              int newDiff = Math.abs(newX - screenResolution.x) + Math.abs(newY - screenResolution.y);
              if (newDiff == 0) {
                  bestX = newX;
                  bestY = newY;
                  break;
              } else if (newDiff < diff) {
                  bestX = newX;
                  bestY = newY;
                  diff = newDiff;
              }
  
          }
  
          if (bestX > 0 && bestY > 0) {
              return new Point(bestX, bestY);
          }
          return null;
      }
  
      private static int findBestMotZoomValue(CharSequence stringValues, int tenDesiredZoom) {
          int tenBestValue = 0;
          for (String stringValue : COMMA_PATTERN.split(stringValues)) {
              stringValue = stringValue.trim();
              double value;
              try {
                  value = Double.parseDouble(stringValue);
              } catch (NumberFormatException nfe) {
                  return tenDesiredZoom;
              }
              int tenValue = (int) (10.0 * value);
              if (Math.abs(tenDesiredZoom - value) < Math.abs(tenDesiredZoom - tenBestValue)) {
                  tenBestValue = tenValue;
              }
          }
          return tenBestValue;
      }
  
      private void setFlash(Camera.Parameters parameters) {
          // FIXME: This is a hack to turn the flash off on the Samsung Galaxy.
          // And this is a hack-hack to work around a different value on the Behold II
          // Restrict Behold II check to Cupcake, per Samsung's advice
          //if (Build.MODEL.contains("Behold II") &&
          //    CameraManager.SDK_INT == Build.VERSION_CODES.CUPCAKE) {
          if (Build.MODEL.contains("Behold II") && CameraManager.SDK_INT == 3) { // 3 = Cupcake
              parameters.set("flash-value", 1);
          } else {
              parameters.set("flash-value", 2);
          }
          // This is the standard setting to turn the flash off that all devices should honor.
          parameters.set("flash-mode", "off");
      }
  
      private void setZoom(Camera.Parameters parameters) {
  
          String zoomSupportedString = parameters.get("zoom-supported");
          if (zoomSupportedString != null && !Boolean.parseBoolean(zoomSupportedString)) {
              return;
          }
  
          int tenDesiredZoom = TEN_DESIRED_ZOOM;
  
          String maxZoomString = parameters.get("max-zoom");
          if (maxZoomString != null) {
              try {
                  int tenMaxZoom = (int) (10.0 * Double.parseDouble(maxZoomString));
                  if (tenDesiredZoom > tenMaxZoom) {
                      tenDesiredZoom = tenMaxZoom;
                  }
              } catch (NumberFormatException nfe) {
                  Log.w(TAG, "Bad max-zoom: " + maxZoomString);
              }
          }
  
          String takingPictureZoomMaxString = parameters.get("taking-picture-zoom-max");
          if (takingPictureZoomMaxString != null) {
              try {
                  int tenMaxZoom = Integer.parseInt(takingPictureZoomMaxString);
                  if (tenDesiredZoom > tenMaxZoom) {
                      tenDesiredZoom = tenMaxZoom;
                  }
              } catch (NumberFormatException nfe) {
                  Log.w(TAG, "Bad taking-picture-zoom-max: " + takingPictureZoomMaxString);
              }
          }
  
          String motZoomValuesString = parameters.get("mot-zoom-values");
          if (motZoomValuesString != null) {
              tenDesiredZoom = findBestMotZoomValue(motZoomValuesString, tenDesiredZoom);
          }
  
          String motZoomStepString = parameters.get("mot-zoom-step");
          if (motZoomStepString != null) {
              try {
                  double motZoomStep = Double.parseDouble(motZoomStepString.trim());
                  int tenZoomStep = (int) (10.0 * motZoomStep);
                  if (tenZoomStep > 1) {
                      tenDesiredZoom -= tenDesiredZoom % tenZoomStep;
                  }
              } catch (NumberFormatException nfe) {
                  // continue
              }
          }
  
          // Set zoom. This helps encourage the user to pull back.
          // Some devices like the Behold have a zoom parameter
          if (maxZoomString != null || motZoomValuesString != null) {
              parameters.set("zoom", String.valueOf(tenDesiredZoom / 10.0));
          }
  
          // Most devices, like the Hero, appear to expose this zoom parameter.
          // It takes on values like "27" which appears to mean 2.7x zoom
          if (takingPictureZoomMaxString != null) {
              parameters.set("taking-picture-zoom", tenDesiredZoom);
          }
      }
  
      public static int getDesiredSharpness() {
          return DESIRED_SHARPNESS;
      }
  
  }
  