|
@@ -0,0 +1,527 @@
|
|
|
+package com.wzl.test_module;
|
|
|
+
|
|
|
+import androidx.annotation.NonNull;
|
|
|
+import androidx.appcompat.app.AppCompatActivity;
|
|
|
+
|
|
|
+import android.graphics.Bitmap;
|
|
|
+import android.graphics.BitmapFactory;
|
|
|
+import android.graphics.ImageFormat;
|
|
|
+import android.graphics.Matrix;
|
|
|
+import android.graphics.Rect;
|
|
|
+import android.graphics.YuvImage;
|
|
|
+import android.hardware.Camera;
|
|
|
+import android.media.CamcorderProfile;
|
|
|
+import android.media.MediaRecorder;
|
|
|
+import android.os.Bundle;
|
|
|
+import android.os.Environment;
|
|
|
+import android.util.DisplayMetrics;
|
|
|
+import android.util.Log;
|
|
|
+import android.view.Surface;
|
|
|
+import android.view.SurfaceHolder;
|
|
|
+import android.view.SurfaceView;
|
|
|
+import android.view.View;
|
|
|
+import android.widget.Button;
|
|
|
+
|
|
|
+import java.io.BufferedOutputStream;
|
|
|
+import java.io.ByteArrayInputStream;
|
|
|
+import java.io.ByteArrayOutputStream;
|
|
|
+import java.io.File;
|
|
|
+import java.io.FileOutputStream;
|
|
|
+import java.io.IOException;
|
|
|
+import java.util.List;
|
|
|
+
|
|
|
+public class MainActivity extends AppCompatActivity implements View.OnClickListener {
|
|
|
+ private final static String TAG = "CameraTest";
|
|
|
+
|
|
|
+ private SurfaceView surfaceView;
|
|
|
+ private Button btnBack;
|
|
|
+ private Button btnShot;
|
|
|
+ private Button btnRecord;
|
|
|
+ private Button btnFlash;
|
|
|
+ private Button btnCameraSwitch;
|
|
|
+
|
|
|
+ private Camera mCamera;
|
|
|
+ private SurfaceHolder mHolder;
|
|
|
+ private MediaRecorder mediaRecorder;
|
|
|
+ private boolean recording = false;
|
|
|
+ private boolean lightOn = false;
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 拍照id 1: 前摄像头 0:后摄像头
|
|
|
+ */
|
|
|
+ private int mCameraId = 0;
|
|
|
+
|
|
|
+ private int picWidth = 1080;
|
|
|
+ private int picHeight = 1920;
|
|
|
+ private int videoProfile = CamcorderProfile.QUALITY_720P; //默认720P
|
|
|
+
|
|
|
+ @Override
|
|
|
+ protected void onCreate(Bundle savedInstanceState) {
|
|
|
+ super.onCreate(savedInstanceState);
|
|
|
+ setContentView(R.layout.activity_main);
|
|
|
+
|
|
|
+ surfaceView = findViewById(R.id.camera_surface_view);
|
|
|
+ btnBack = findViewById(R.id.iv_back);
|
|
|
+ btnShot = findViewById(R.id.img_camera);
|
|
|
+ btnRecord = findViewById(R.id.iv_record);
|
|
|
+ btnFlash = findViewById(R.id.camera_flash);
|
|
|
+ btnCameraSwitch = findViewById(R.id.camera_switch);
|
|
|
+
|
|
|
+ btnBack.setOnClickListener(this);
|
|
|
+ btnShot.setOnClickListener(this);
|
|
|
+ btnRecord.setOnClickListener(this);
|
|
|
+ btnFlash.setOnClickListener(this);
|
|
|
+ btnCameraSwitch.setOnClickListener(this);
|
|
|
+ surfaceView.setOnClickListener(this);
|
|
|
+
|
|
|
+ if (mCamera == null) {
|
|
|
+ mCamera = getCamera(mCameraId);
|
|
|
+ }
|
|
|
+
|
|
|
+ mHolder = surfaceView.getHolder();
|
|
|
+ mHolder.addCallback(new SurfaceHolder.Callback() {
|
|
|
+ @Override
|
|
|
+ public void surfaceCreated(@NonNull SurfaceHolder holder) {
|
|
|
+ //开启预览
|
|
|
+ if (mCamera != null) {
|
|
|
+ startPreview(mCamera, holder);
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ @Override
|
|
|
+ public void surfaceChanged(@NonNull SurfaceHolder holder, int format, int width, int height) {
|
|
|
+ if (mCamera != null) {
|
|
|
+ mCamera.stopPreview();
|
|
|
+ startPreview(mCamera, holder);
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ @Override
|
|
|
+ public void surfaceDestroyed(@NonNull SurfaceHolder holder) {
|
|
|
+ releaseCamera();
|
|
|
+ }
|
|
|
+ });
|
|
|
+ }
|
|
|
+
|
|
|
+ @Override
|
|
|
+ protected void onResume() {
|
|
|
+ super.onResume();
|
|
|
+
|
|
|
+ if (mCamera == null) {
|
|
|
+ mCamera = getCamera(mCameraId);
|
|
|
+ if (mHolder != null) {
|
|
|
+ startPreview(mCamera, mHolder);
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ @Override
|
|
|
+ protected void onDestroy() {
|
|
|
+ releaseCamera();
|
|
|
+
|
|
|
+ super.onDestroy();
|
|
|
+ }
|
|
|
+
|
|
|
+ @Override
|
|
|
+ public void onClick(View v) {
|
|
|
+ int id = v.getId();
|
|
|
+ if (id == R.id.iv_back) {
|
|
|
+ finish();
|
|
|
+ } else if (id == R.id.img_camera) {
|
|
|
+ takePhoto();
|
|
|
+ } else if (id == R.id.camera_switch) {
|
|
|
+ switchCamera();
|
|
|
+ } else if (id == R.id.camera_flash) {
|
|
|
+ switchFlashLight();
|
|
|
+ } else if (id == R.id.iv_record) {
|
|
|
+ recordVideo();
|
|
|
+ } else if (id == R.id.camera_surface_view) {
|
|
|
+ autoFocus();
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ private Camera getCamera(int id) {
|
|
|
+ Camera camera = null;
|
|
|
+ try {
|
|
|
+ camera = Camera.open(id);
|
|
|
+ } catch (Exception e) {
|
|
|
+ Log.e(TAG, "getCamera: " + e);
|
|
|
+ }
|
|
|
+ return camera;
|
|
|
+ }
|
|
|
+
|
|
|
+ private void releaseCamera() {
|
|
|
+ if (mCamera != null) {
|
|
|
+ mCamera.setPreviewCallback(null);
|
|
|
+ mCamera.stopPreview();
|
|
|
+ mCamera.release();
|
|
|
+ mCamera = null;
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ public void setPicSize(int width, int height) {
|
|
|
+ picHeight = height;
|
|
|
+ picWidth = width;
|
|
|
+ }
|
|
|
+
|
|
|
+ private void autoFocus() {
|
|
|
+ try {
|
|
|
+ if (mCamera != null) {
|
|
|
+ mCamera.cancelAutoFocus();
|
|
|
+ mCamera.getParameters().setFocusMode(Camera.Parameters.FOCUS_MODE_AUTO);
|
|
|
+ mCamera.autoFocus(new Camera.AutoFocusCallback() {
|
|
|
+ @Override
|
|
|
+ public void onAutoFocus(boolean success, Camera camera) {
|
|
|
+ //
|
|
|
+ }
|
|
|
+ });
|
|
|
+ }
|
|
|
+ } catch (Exception e) {
|
|
|
+ e.printStackTrace();
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ private void takePhoto() {
|
|
|
+ if (recording) {
|
|
|
+ Log.e(TAG, "Recording video busy...");
|
|
|
+ } else {
|
|
|
+ mCamera.takePicture(null, null, pictureCallback);
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ private final Camera.PictureCallback pictureCallback = new Camera.PictureCallback() {
|
|
|
+ @Override
|
|
|
+ public void onPictureTaken(final byte[] data, Camera camera) {
|
|
|
+ new Thread(new Runnable() {
|
|
|
+ @Override
|
|
|
+ public void run() {
|
|
|
+ Bitmap bitmap = BitmapFactory.decodeByteArray(data, 0, data.length);
|
|
|
+ Bitmap saveBitmap = setTakePictureOrientation(mCameraId, bitmap);
|
|
|
+ saveBitmap = Bitmap.createScaledBitmap(saveBitmap, picWidth, picHeight, true);
|
|
|
+ String imgPath = getExternalFilesDir(Environment.DIRECTORY_DCIM).getPath() +
|
|
|
+ File.separator + System.currentTimeMillis() + ".jpg";
|
|
|
+ Log.e(TAG, "imgPath: --- " + imgPath);
|
|
|
+
|
|
|
+ saveJPGE_After(saveBitmap, imgPath, 100);
|
|
|
+ if (!bitmap.isRecycled()) {
|
|
|
+ bitmap.recycle();
|
|
|
+ }
|
|
|
+ if (!saveBitmap.isRecycled()) {
|
|
|
+ saveBitmap.recycle();
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }).start();
|
|
|
+
|
|
|
+ if (mCamera != null) {
|
|
|
+ mCamera.stopPreview();
|
|
|
+ if (mHolder != null) {
|
|
|
+ startPreview(mCamera, mHolder);
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+ };
|
|
|
+
|
|
|
+ public boolean saveJPGE_After(Bitmap bitmap, String path, int quality) {
|
|
|
+ File file = new File(path);
|
|
|
+ makeDir(file);
|
|
|
+ try {
|
|
|
+ FileOutputStream out = new FileOutputStream(file);
|
|
|
+ if (bitmap.compress(Bitmap.CompressFormat.JPEG, quality, out)) {
|
|
|
+ out.flush();
|
|
|
+ out.close();
|
|
|
+ }
|
|
|
+ } catch (Exception e) {
|
|
|
+ e.printStackTrace();
|
|
|
+ return false;
|
|
|
+ }
|
|
|
+ return true;
|
|
|
+ }
|
|
|
+
|
|
|
+ private void makeDir(File file) {
|
|
|
+ File tempPath = new File(file.getParent());
|
|
|
+ if (!tempPath.exists()) {
|
|
|
+ tempPath.mkdirs();
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ public Bitmap setTakePictureOrientation(int id, Bitmap bitmap) {
|
|
|
+ Camera.CameraInfo info = new Camera.CameraInfo();
|
|
|
+ Camera.getCameraInfo(id, info);
|
|
|
+ bitmap = rotateImageView(id, info.orientation, bitmap);
|
|
|
+ return bitmap;
|
|
|
+ }
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 把相机拍照返回照片转正
|
|
|
+ *
|
|
|
+ * @param angle 旋转角度
|
|
|
+ * @return bitmap 图片
|
|
|
+ */
|
|
|
+ private Bitmap rotateImageView(int id, int angle, Bitmap bitmap) {
|
|
|
+ //矩阵
|
|
|
+ Matrix matrix = new Matrix();
|
|
|
+ matrix.postRotate(angle);
|
|
|
+ //加入翻转 把相机拍照返回照片转正
|
|
|
+ if (id == 1) {
|
|
|
+ matrix.postScale(-1, 1);
|
|
|
+ }
|
|
|
+ // 创建新的图片
|
|
|
+ return Bitmap.createBitmap(bitmap, 0, 0,
|
|
|
+ bitmap.getWidth(), bitmap.getHeight(), matrix, true);
|
|
|
+ }
|
|
|
+
|
|
|
+ public void switchCamera() {
|
|
|
+ releaseCamera();
|
|
|
+ mCameraId = (mCameraId + 1) % Camera.getNumberOfCameras();
|
|
|
+ mCamera = getCamera(mCameraId);
|
|
|
+ if (mHolder != null) {
|
|
|
+ startPreview(mCamera, mHolder);
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ public void switchFlashLight() {
|
|
|
+ if (lightOn) {
|
|
|
+ turnLightOff();
|
|
|
+ lightOn = false;
|
|
|
+ } else {
|
|
|
+ turnLightOn();
|
|
|
+ lightOn = true;
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ public void turnLightOn() {
|
|
|
+ if (mCamera == null) {
|
|
|
+ return;
|
|
|
+ }
|
|
|
+ Camera.Parameters parameters = mCamera.getParameters();
|
|
|
+ if (parameters == null) {
|
|
|
+ return;
|
|
|
+ }
|
|
|
+ parameters.setFlashMode(Camera.Parameters.FLASH_MODE_TORCH);//开启
|
|
|
+ mCamera.setParameters(parameters);
|
|
|
+ }
|
|
|
+
|
|
|
+ public void turnLightOff() {
|
|
|
+ if (mCamera == null) {
|
|
|
+ return;
|
|
|
+ }
|
|
|
+ Camera.Parameters parameters = mCamera.getParameters();
|
|
|
+ if (parameters == null) {
|
|
|
+ return;
|
|
|
+ }
|
|
|
+ parameters.setFlashMode(Camera.Parameters.FLASH_MODE_OFF);
|
|
|
+ mCamera.setParameters(parameters);
|
|
|
+ }
|
|
|
+
|
|
|
+ public void recordVideo() {
|
|
|
+ try {
|
|
|
+ if (!recording) {
|
|
|
+ Log.d(TAG, "start recording video ");
|
|
|
+ if (prepareVideoRecorder()) {
|
|
|
+ mediaRecorder.start();
|
|
|
+ recording = true;
|
|
|
+ }
|
|
|
+ } else {
|
|
|
+ Log.d(TAG, "stop recording video ");
|
|
|
+
|
|
|
+ mediaRecorder.stop();
|
|
|
+ releaseMediaRecorder();
|
|
|
+ mCamera.lock();
|
|
|
+ recording = false;
|
|
|
+
|
|
|
+ if (mCamera != null) {
|
|
|
+ mCamera.stopPreview();
|
|
|
+ if (mHolder != null) {
|
|
|
+ startPreview(mCamera, mHolder);
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+ } catch (Exception e) {
|
|
|
+ e.printStackTrace();
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ private boolean prepareVideoRecorder() {
|
|
|
+ try {
|
|
|
+ Log.d(TAG, "prepare video recorder ");
|
|
|
+ if (mediaRecorder == null) {
|
|
|
+ mediaRecorder = new MediaRecorder();
|
|
|
+ mediaRecorder.reset();
|
|
|
+ }
|
|
|
+
|
|
|
+ /*camera相关设置部分*/
|
|
|
+ if (mCamera != null) {
|
|
|
+ //camera?.setDisplayOrientation(90)
|
|
|
+ mCamera.unlock();
|
|
|
+ mediaRecorder.setCamera(mCamera);
|
|
|
+ }
|
|
|
+
|
|
|
+ /*recorder设置部分*/
|
|
|
+ mediaRecorder.setAudioSource(MediaRecorder.AudioSource.CAMCORDER);
|
|
|
+ mediaRecorder.setVideoSource(MediaRecorder.VideoSource.CAMERA);
|
|
|
+ CamcorderProfile profile = CamcorderProfile.get(mCameraId, CamcorderProfile.QUALITY_HIGH);
|
|
|
+ if (CamcorderProfile.hasProfile(mCameraId, videoProfile)) {
|
|
|
+ profile = CamcorderProfile.get(mCameraId, videoProfile);
|
|
|
+ }
|
|
|
+
|
|
|
+ String videoPath = getExternalFilesDir(Environment.DIRECTORY_DCIM).getPath();
|
|
|
+ File videoFile = new File(videoPath);
|
|
|
+ if (!videoFile.exists()) {
|
|
|
+ videoFile.mkdirs();
|
|
|
+ }
|
|
|
+
|
|
|
+ String path = videoPath + File.separator + System.currentTimeMillis() + "_video.mp4";
|
|
|
+ Log.e(TAG, "video file path: --- " + path);
|
|
|
+ mediaRecorder.setProfile(profile);
|
|
|
+ mediaRecorder.setOutputFile(path);
|
|
|
+ mediaRecorder.setPreviewDisplay(mHolder.getSurface());
|
|
|
+ mediaRecorder.prepare();
|
|
|
+ return true;
|
|
|
+ } catch (Exception e) {
|
|
|
+ Log.e(TAG, "prepare video recorder error!!");
|
|
|
+ e.printStackTrace();
|
|
|
+ }
|
|
|
+
|
|
|
+ return false;
|
|
|
+ }
|
|
|
+
|
|
|
+ private void releaseMediaRecorder() {
|
|
|
+ Log.d(TAG, "release video recorder ");
|
|
|
+ try {
|
|
|
+ if (mediaRecorder != null) {
|
|
|
+ mediaRecorder.reset(); // clear recorder configuration
|
|
|
+ mediaRecorder.release(); // release the recorder object
|
|
|
+ mediaRecorder = null;
|
|
|
+ mCamera.lock(); // lock camera for later use
|
|
|
+ }
|
|
|
+ } catch (Exception e) {
|
|
|
+ e.printStackTrace();
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 预览相机
|
|
|
+ */
|
|
|
+ private void startPreview(Camera camera, SurfaceHolder holder) {
|
|
|
+ try {
|
|
|
+ // 确认相机预览尺寸
|
|
|
+ setupCamera(camera);
|
|
|
+ camera.setPreviewDisplay(holder);
|
|
|
+ setCameraDisplayOrientation(mCameraId, camera);
|
|
|
+ camera.startPreview();
|
|
|
+ } catch (Exception e) {
|
|
|
+ e.printStackTrace();
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ public void setCameraDisplayOrientation(int cameraId, Camera camera) {
|
|
|
+ android.hardware.Camera.CameraInfo info =
|
|
|
+ new android.hardware.Camera.CameraInfo();
|
|
|
+ android.hardware.Camera.getCameraInfo(cameraId, info);
|
|
|
+ int rotation = getWindowManager().getDefaultDisplay().getRotation();
|
|
|
+ int degrees = 0;
|
|
|
+ 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;
|
|
|
+ default:
|
|
|
+ break;
|
|
|
+ }
|
|
|
+ int result;
|
|
|
+ if (info.facing == Camera.CameraInfo.CAMERA_FACING_FRONT) {
|
|
|
+ result = (info.orientation + degrees) % 360;
|
|
|
+ result = (360 - result) % 360;
|
|
|
+ } else {
|
|
|
+ result = (info.orientation - degrees + 360) % 360;
|
|
|
+ }
|
|
|
+ //设置角度
|
|
|
+ camera.setDisplayOrientation(result);
|
|
|
+ }
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 设置surfaceView的尺寸 因为camera默认是横屏,所以取得支持尺寸也都是横屏的尺寸
|
|
|
+ * 我们在startPreview方法里面把它矫正了过来,但是这里我们设置设置surfaceView的尺寸的时候要注意 previewSize.height<previewSize.width
|
|
|
+ * previewSize.width才是surfaceView的高度
|
|
|
+ * 一般相机都是屏幕的宽度 这里设置为屏幕宽度 高度自适应 你也可以设置自己想要的大小
|
|
|
+ */
|
|
|
+ private void setupCamera(Camera camera) {
|
|
|
+ Camera.Parameters parameters = camera.getParameters();
|
|
|
+ if (parameters.getSupportedFocusModes().contains(
|
|
|
+ Camera.Parameters.FOCUS_MODE_CONTINUOUS_PICTURE)) {
|
|
|
+ parameters.setFocusMode(Camera.Parameters.FOCUS_MODE_CONTINUOUS_PICTURE);
|
|
|
+ }
|
|
|
+
|
|
|
+ List<Camera.Size> sizeList = parameters.getSupportedPreviewSizes();//获取所有支持的camera尺寸
|
|
|
+ //Log.d(TAG,"optionSize : mSurfaceView "+surfaceView.getWidth()+" * "+surfaceView.getHeight());
|
|
|
+ Camera.Size optionSize = getOptimalPreviewSize(sizeList, picHeight, picWidth);//获取一个最为适配的camera.size
|
|
|
+ Log.d(TAG,"optionSize : "+optionSize.width+" * "+optionSize.height);
|
|
|
+
|
|
|
+ if (optionSize.width > optionSize.height) {
|
|
|
+ picWidth = optionSize.height;
|
|
|
+ picHeight = optionSize.width;
|
|
|
+ } else {
|
|
|
+ picWidth = optionSize.width;
|
|
|
+ picHeight = optionSize.height;
|
|
|
+ }
|
|
|
+ parameters.setPreviewSize(optionSize.width,optionSize.height);//把camera.size赋值到parameters
|
|
|
+ mCamera.setParameters(parameters);
|
|
|
+
|
|
|
+
|
|
|
+ //根据屏幕尺寸获取最佳 大小
|
|
|
+ /*Camera.Size previewSize = cameraInstance.getPicPreviewSize(parameters.getSupportedPreviewSizes(),
|
|
|
+ screenHeight, screenWidth);
|
|
|
+ parameters.setPreviewSize(previewSize.width, previewSize.height);
|
|
|
+
|
|
|
+ Camera.Size pictrueSize = cameraInstance.getPicPreviewSize(parameters.getSupportedPictureSizes(),
|
|
|
+ screenHeight,screenWidth);
|
|
|
+ parameters.setPictureSize(pictrueSize.width, pictrueSize.height);
|
|
|
+ camera.setParameters(parameters);
|
|
|
+ // picHeight = (screenWidth * pictrueSize.width) / pictrueSize.height;
|
|
|
+ picWidth = pictrueSize.width;
|
|
|
+ picHeight = pictrueSize.height;
|
|
|
+ FrameLayout.LayoutParams params = new FrameLayout.LayoutParams(screenWidth,
|
|
|
+ (screenWidth * pictrueSize.width) / pictrueSize.height);
|
|
|
+ svContent.setLayoutParams(params);*/
|
|
|
+ }
|
|
|
+
|
|
|
+ private Camera.Size getOptimalPreviewSize(List<Camera.Size> sizes, int w, int h) {
|
|
|
+ final double ASPECT_TOLERANCE = 0.2;
|
|
|
+ double targetRatio = (double) w / h;
|
|
|
+ if (sizes == null) return null;
|
|
|
+
|
|
|
+ Camera.Size optimalSize = null;
|
|
|
+ double minDiff = Double.MAX_VALUE;
|
|
|
+
|
|
|
+ // Try to find an size match aspect ratio and size
|
|
|
+ for (Camera.Size size : sizes) {
|
|
|
+ double ratio = (double) size.width / size.height;
|
|
|
+ if (Math.abs(ratio - targetRatio) > ASPECT_TOLERANCE) continue;
|
|
|
+ if (Math.abs(size.height - h) < minDiff) {
|
|
|
+ optimalSize = size;
|
|
|
+ minDiff = Math.abs(size.height - h);
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ // Cannot find the one match the aspect ratio, ignore the requirement
|
|
|
+ if (optimalSize == null) {
|
|
|
+ minDiff = Double.MAX_VALUE;
|
|
|
+ for (Camera.Size size : sizes) {
|
|
|
+ if (Math.abs(size.height - h) < minDiff) {
|
|
|
+ optimalSize = size;
|
|
|
+ minDiff = Math.abs(size.height - h);
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+ return optimalSize;
|
|
|
+ }
|
|
|
+}
|