package org.thoughtcrime.securesms.components.camera; import android.app.Activity; import android.hardware.Camera; import android.hardware.Camera.CameraInfo; import android.hardware.Camera.Parameters; import android.hardware.Camera.Size; import android.support.annotation.NonNull; import android.support.annotation.Nullable; import android.util.DisplayMetrics; import android.util.Log; import android.view.Surface; import java.util.Collections; import java.util.Comparator; import java.util.LinkedList; import java.util.List; @SuppressWarnings("deprecation") public class CameraUtils { private static final String TAG = CameraUtils.class.getSimpleName(); /* * modified from: https://github.com/commonsguy/cwac-camera/blob/master/camera/src/com/commonsware/cwac/camera/CameraUtils.java */ public static @Nullable Size getPreferredPreviewSize(int displayOrientation, int width, int height, @NonNull Parameters parameters) { final int targetWidth = displayOrientation % 180 == 90 ? height : width; final int targetHeight = displayOrientation % 180 == 90 ? width : height; final double targetRatio = (double) targetWidth / targetHeight; Log.w(TAG, String.format("getPreferredPreviewSize(%d, %d, %d) -> target %dx%d, AR %.02f", displayOrientation, width, height, targetWidth, targetHeight, targetRatio)); List<Size> sizes = parameters.getSupportedPreviewSizes(); List<Size> ideals = new LinkedList<>(); List<Size> bigEnough = new LinkedList<>(); for (Size size : sizes) { Log.w(TAG, String.format(" %dx%d (%.02f)", size.width, size.height, (float)size.width / size.height)); if (size.height == size.width * targetRatio && size.height >= targetHeight && size.width >= targetWidth) { ideals.add(size); Log.w(TAG, " (ideal ratio)"); } else if (size.width >= targetWidth && size.height >= targetHeight) { bigEnough.add(size); Log.w(TAG, " (good size, suboptimal ratio)"); } } if (!ideals.isEmpty()) return Collections.min(ideals, new AreaComparator()); else if (!bigEnough.isEmpty()) return Collections.min(bigEnough, new AspectRatioComparator(targetRatio)); else return Collections.max(sizes, new AreaComparator()); } // based on // http://developer.android.com/reference/android/hardware/Camera.html#setDisplayOrientation(int) // and http://stackoverflow.com/a/10383164/115145 public static int getCameraDisplayOrientation(@NonNull Activity activity, @NonNull CameraInfo info) { int rotation = activity.getWindowManager().getDefaultDisplay().getRotation(); int degrees = 0; DisplayMetrics dm = new DisplayMetrics(); activity.getWindowManager().getDefaultDisplay().getMetrics(dm); switch (rotation) { 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; } if (info.facing == Camera.CameraInfo.CAMERA_FACING_FRONT) { return (360 - ((info.orientation + degrees) % 360)) % 360; } else { return (info.orientation - degrees + 360) % 360; } } private static class AreaComparator implements Comparator<Size> { @Override public int compare(Size lhs, Size rhs) { return Long.signum(lhs.width * lhs.height - rhs.width * rhs.height); } } private static class AspectRatioComparator extends AreaComparator { private final double target; public AspectRatioComparator(double target) { this.target = target; } @Override public int compare(Size lhs, Size rhs) { final double lhsDiff = Math.abs(target - (double) lhs.width / lhs.height); final double rhsDiff = Math.abs(target - (double) rhs.width / rhs.height); if (lhsDiff < rhsDiff) return -1; else if (lhsDiff > rhsDiff) return 1; else return super.compare(lhs, rhs); } } }