package com.fastebro.androidrgbtool.utils;
import android.app.Activity;
import android.content.Context;
import android.hardware.Camera;
import android.hardware.camera2.CameraAccessException;
import android.hardware.camera2.CameraCharacteristics;
import android.hardware.camera2.CameraManager;
import android.support.annotation.NonNull;
import android.view.Surface;
import android.view.WindowManager;
import java.util.List;
/**
* Created by danielealtomare on 26/04/16.
* Project: rgb-tool
*/
public final class CameraUtils {
private static final double ASPECT_TOLERANCE = 0.15;
private CameraUtils() {
}
/**
* Calculate the optimal size of camera preview according to layout used to display this preview
*
* @param sizes Available camera preview sizes
* @param layoutWidth width of layout used to display the preview
* @param layoutHeight height of the layout used to display the preview
* @param isPortrait indicate if current orientation is portrait since the camera sizes are all in landscape mode
* @return best camera preview size which fit layout used to display the preview
*/
public static Camera.Size getBestPreviewSize(List<Camera.Size> sizes, int layoutWidth, int layoutHeight, boolean
isPortrait) {
if (isPortrait) {
// Inverse surfaceWidth and surfaceHeight since the sizes are all in landscape mode.
layoutHeight = layoutHeight + layoutWidth;
layoutWidth = layoutHeight - layoutWidth;
layoutHeight = layoutHeight - layoutWidth;
}
double targetRatio = (double) layoutWidth / layoutHeight;
Camera.Size optimalSize = null;
double optimalArea = 0;
// Try to find the size that matches the target ratio and has the max area.
for (Camera.Size candidateSize : sizes) {
double candidateRatio = (double) candidateSize.width / candidateSize.height;
double candidateArea = candidateSize.width * candidateSize.height;
double ratioDifference = Math.abs(candidateRatio - targetRatio);
if (ratioDifference < ASPECT_TOLERANCE && candidateArea > optimalArea) {
optimalSize = candidateSize;
optimalArea = candidateArea;
}
}
// Cannot find a size that matches the target ratio.
// Try to find the size that has the max area.
if (optimalSize == null) {
optimalArea = 0;
for (Camera.Size candidateSize : sizes) {
double candidateArea = candidateSize.width * candidateSize.height;
if (candidateArea > optimalArea) {
optimalSize = candidateSize;
optimalArea = candidateArea;
}
}
}
return optimalSize;
}
/**
* calculate proportional layout dimension for displaying a camera preview according to a given camera preview size
*
* @param size Camera preview size used {@see CameraUtils.getBestPreviewSize}
* @param targetW current width of the layout which will host camera preview
* @param targetH current height of the layout which will host camera preview
* @param isPortrait indicate if current orientation is portrait since the camera sizes are all in landscape mode
* @return dimension which matches camera preview size ratio
*/
public static int[] getProportionalDimension(Camera.Size size, int targetW, int targetH, boolean isPortrait) {
int[] adaptedDimension = new int[2];
double previewRatio;
if (isPortrait) {
previewRatio = (double) size.height / size.width;
} else {
previewRatio = (double) size.width / size.height;
}
if (((double) targetW / targetH) > previewRatio) {
adaptedDimension[0] = targetW;
adaptedDimension[1] = (int) (adaptedDimension[0] / previewRatio);
} else {
adaptedDimension[1] = targetH;
adaptedDimension[0] = (int) (adaptedDimension[1] * previewRatio);
}
return adaptedDimension;
}
/**
* Adapt the {@link android.hardware.Camera} display orientaiton to the current device orientation.
*
* @param context a {@link android.content.Context} to retrieve device orientation.
* @param camera the {@link android.hardware.Camera} to be adapted.
*/
public static void setCameraDisplayOrientation(Context context, android.hardware.Camera camera) {
final Camera.CameraInfo info = new android.hardware.Camera.CameraInfo();
Camera.getCameraInfo(Camera.CameraInfo.CAMERA_FACING_BACK, info);
int degrees = 0;
final int currentRotation = ((WindowManager) context.getSystemService(Activity.WINDOW_SERVICE))
.getDefaultDisplay().getRotation();
switch (currentRotation) {
case Surface.ROTATION_0:
degrees = 0;
break;
case Surface.ROTATION_90:
degrees = 90;
break;
case Surface.ROTATION_180:
degrees = 180;
break;
case Surface.ROTATION_270:
degrees = 270;
break;
}
int displayOrientation;
if (info.facing == Camera.CameraInfo.CAMERA_FACING_FRONT) {
displayOrientation = (info.orientation + degrees) % 360;
displayOrientation = (360 - displayOrientation) % 360; // compensate the mirror
} else { // back-facing
displayOrientation = (info.orientation - degrees + 360) % 360;
}
camera.setDisplayOrientation(displayOrientation);
}
public static String getCameraId(@NonNull CameraManager cameraManager, int lensFacing) {
try {
String cameraId;
int cameraOrientation;
CameraCharacteristics characteristics;
for (int i = 0; i < cameraManager.getCameraIdList().length; i++) {
cameraId = cameraManager.getCameraIdList()[i];
characteristics = cameraManager.getCameraCharacteristics(cameraId);
cameraOrientation = characteristics.get(CameraCharacteristics.LENS_FACING);
if (cameraOrientation == lensFacing) {
return cameraId;
}
}
} catch (CameraAccessException e) {
}
return null;
}
}