2016-12-18 10 views
2

Я создаю приложение для Android с функциональностью камеры. Экран камеры содержит панель инструментов сверху, обзор поверхности (предварительный просмотр камеры) под панелью инструментов и кнопки управления камерой в нижней части экрана. Экран всегда находится в портретной ориентации.Как исправить правильное соотношение сторон камеры (просмотр поверхности) в Android?

[Некоторые строки кода не связаны с вопросом удаляются]

Это мой фрагмент FragmentCamera

import android.hardware.Camera; 
import android.media.CamcorderProfile; 
import android.media.MediaRecorder; 
import android.os.Bundle; 
import android.util.Log; 
import android.view.LayoutInflater; 
import android.view.SurfaceView; 
import android.view.View; 
import android.view.ViewGroup; 
import android.widget.ImageView; 
import com.dmc.R; 
import com.dmc.entities.Preview; 

public class CameraFragment implements View.OnClickListener, View.OnTouchListener { 

    public static final String ARG_CAMERA_MODE = "camera.mode"; 
    public static final String TYPE_CAMERA_MODE_IMAGE = "image"; 
    public static final String TYPE_CAMERA_MODE_VIDEO = "video"; 
    public MediaRecorder mrec = new MediaRecorder(); 

    private Camera camera; 
    private String mCameraMode = TYPE_CAMERA_MODE_IMAGE; //or video 
    private com.dmc.entities.Preview preview; 
    private ImageView btnStopRecording; 
    private SurfaceView surfaceView; 
    private View view; 

    public static FrCamera getInstance(String cameraMode) { 
     CameraFragment fragment = new CameraFragment(); 
     Bundle bundle = new Bundle(1); 
     bundle.putString(ARG_CAMERA_MODE, cameraMode); 
     return fragment.setArguments(bundle); 
    } 

    @Override 
    public void onCreate(Bundle savedInstanceState) { 
     super.onCreate(savedInstanceState); 
     mCameraMode = getArguments().getString(ARG_CAMERA_MODE); 
    } 

    @Override 
    public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) { 
     view = inflater.inflate(R.layout.fragment_camera, container, false); 
     view.setOnTouchListener(this); 
     btnStopRecording = (ImageView) view.findViewById(R.id.btnStopRecording); 
     if (!mCameraMode.equals(TYPE_CAMERA_MODE_IMAGE)) { 
      btnStopRecording.setOnClickListener(this); 
     } 
     surfaceView = (SurfaceView) view.findViewById(R.id.surfaceView); 
     view.findViewById(R.id.imgCameraTakePicture).setOnClickListener(this); 

     preview = new Preview(getActivity(), (SurfaceView) view.findViewById(R.id.surfaceView)); 
     preview.setKeepScreenOn(true); 
     return view; 
    } 

    @Override 
    public void onStart() { 
     super.onStart(); 

     int numCams = Camera.getNumberOfCameras(); 
     if (numCams > 0) { 
      try { 
       camera = Camera.open(0); 
       preview.setCamera(camera); 
       camera.startPreview(); 
      } catch (RuntimeException ex) { 
      } 
     } 
    } 

    @Override 
    public void onPause() { 
     if (camera != null) { 
      camera.stopPreview(); 
      preview.setCamera(null); 
      camera.release(); 
      camera = null; 
     } 
     super.onPause(); 
    } 

    @Override 
    public void onResume() { 
     super.onResume(); 
     camera.startPreview(); 
    } 

    private void startVideoRecording() { 
     try { 
      mrec = new MediaRecorder(); 
      mrec.setCamera(camera); 
      mrec.setVideoSource(MediaRecorder.VideoSource.CAMERA); 
      mrec.setAudioSource(MediaRecorder.AudioSource.MIC); 
      CamcorderProfile profile = CamcorderProfile.get(CamcorderProfile.QUALITY_HIGH); 
      mrec.setProfile(profile); 
      camera.lock(); 
      camera.unlock(); 
      mrec.setPreviewDisplay(preview.mHolder.getSurface()); 
      mrec.setOutputFile(outVideoFile.getPath()); 
      mrec.setOrientationHint(Preview.rotate); 
      mrec.prepare(); 
      mrec.start(); 
     } catch (Exception ex) { 
      Log.e(getClass().getName(), ex.getMessage()); 
     } 
    } 

    protected void stopRecording() { 
     if (mrec != null) { 
      mrec.stop(); 
      mrec.release(); 
     } 
    } 

    @Override 
    public void onClick(View v) { 
     switch (v.getId()) { 
      case R.id.imgCameraTakenPicture: 
       // Save image 
       break; 
      case R.id.btnStopRecording: 
       stopRecording(); 
       break; 
      case R.id.imgCameraTakePicture: 
       if (mCameraMode.equals(TYPE_CAMERA_MODE_IMAGE)) { 
        camera.takePicture(shutterCallback, rawCallback, jpegCallback); 
       } else 
        startVideoRecording(); 
       break; 
     } 
    } 
} 

Это изображение

import android.app.Activity; 
import android.content.Context; 
import android.graphics.PixelFormat; 
import android.hardware.Camera; 
import android.hardware.Camera.Size; 
import android.view.Surface; 
import android.view.SurfaceHolder; 
import android.view.SurfaceView; 
import android.view.View; 
import android.view.ViewGroup; 

import java.io.IOException; 
import java.util.List; 

public class Preview extends ViewGroup implements SurfaceHolder.Callback { 
    public static final float RATIO = 0.75f; 
    public static int rotate; 

    public SurfaceView mSurfaceView; 
    public SurfaceHolder mHolder; 
    Size mPreviewSize; 
    List<Size> mSupportedPreviewSizes; 
    Camera mCamera; 

    public Preview(Context context, SurfaceView sv) { 
     super(context); 
     mSurfaceView = sv; 
     mHolder = mSurfaceView.getHolder(); 
     mHolder.addCallback(this); 
     mHolder.setType(SurfaceHolder.SURFACE_TYPE_PUSH_BUFFERS); 
    } 

    public void setCamera(Camera camera) { 
     mCamera = camera; 
     if (mCamera != null) { 
      mSupportedPreviewSizes = mCamera.getParameters().getSupportedPreviewSizes(); 
      requestLayout(); 
      // get Camera parameters 
      Camera.Parameters params = mCamera.getParameters(); 

      List<String> focusModes = params.getSupportedFocusModes(); 
      if (focusModes.contains(Camera.Parameters.FOCUS_MODE_CONTINUOUS_PICTURE)) { 
       params.setFocusMode(Camera.Parameters.FOCUS_MODE_CONTINUOUS_PICTURE); 
      } else { 
       params.setFocusMode(Camera.Parameters.FOCUS_MODE_AUTO); 
      } 

      params.setJpegThumbnailQuality(100); 
      params.setJpegQuality(100); 

      // Configure image format. RGB_565 is the most common format. 
      List<Integer> formats = params.getSupportedPictureFormats(); 
      if (formats.contains(PixelFormat.RGB_565)) 
       params.setPictureFormat(PixelFormat.RGB_565); 
      else if (formats.contains(PixelFormat.JPEG)) 
       params.setPictureFormat(PixelFormat.JPEG); 
      else params.setPictureFormat(formats.get(0)); 

      Camera.CameraInfo camInfo = new Camera.CameraInfo(); 
      Camera.getCameraInfo(Camera.CameraInfo.CAMERA_FACING_BACK, camInfo); 
      int cameraRotationOffset = camInfo.orientation; 

      Camera.Parameters parameters = mCamera.getParameters(); 

      int rotation = ((Activity) getContext()).getWindowManager().getDefaultDisplay().getRotation(); 
      int degrees = 0; 
      switch (rotation) { 
       case Surface.ROTATION_0: 
        degrees = 0; 
        break; // Natural orientation 
       case Surface.ROTATION_90: 
        degrees = 90; 
        break; // Landscape left 
       case Surface.ROTATION_180: 
        degrees = 180; 
        break;// Upside down 
       case Surface.ROTATION_270: 
        degrees = 270; 
        break;// Landscape right 
      } 
      int displayRotation; 
      if (camInfo.facing == Camera.CameraInfo.CAMERA_FACING_FRONT) { 
       displayRotation = (cameraRotationOffset + degrees) % 360; 
       //displayRotation = (360 - displayRotation) % 360; // compensate the mirror 
      } else { // back-facing 
       displayRotation = (cameraRotationOffset - degrees + 360) % 360; 
      } 
      mCamera.setDisplayOrientation(displayRotation); 

      if (camInfo.facing == Camera.CameraInfo.CAMERA_FACING_FRONT) { 
       rotate = (360 + cameraRotationOffset + degrees) % 360; 
      } else { 
       rotate = (360 + cameraRotationOffset - degrees) % 360; 
      } 

      parameters.set("orientation", "portrait"); 
      parameters.setRotation(rotate); 

      mCamera.setParameters(params); 
     } 
    } 

    @Override 
    protected void onLayout(boolean changed, int l, int t, int r, int b) { 
     if (changed && getChildCount() > 0) { 
      final View child = getChildAt(0); 

      final int width = r - l; 
      final int height = b - t; 

      int previewWidth = width; 
      int previewHeight = height; 
      if (mPreviewSize != null) { 
       previewWidth = mPreviewSize.width; 
       previewHeight = mPreviewSize.height; 
      } 

      // Center the child SurfaceView within the parent. 
      if (width * previewHeight > height * previewWidth) { 
       final int scaledChildWidth = previewWidth * height/previewHeight; 
       child.layout((width - scaledChildWidth)/2, 0, 
         (width + scaledChildWidth)/2, height); 
      } else { 
       final int scaledChildHeight = previewHeight * width/previewWidth; 
       child.layout(0, (height - scaledChildHeight)/2, 
         width, (height + scaledChildHeight)/2); 
      } 
     } 
    } 

    public void surfaceCreated(SurfaceHolder holder) { 
     try { 
      if (mCamera != null) { 
       mCamera.setPreviewDisplay(holder); 
       mCamera.startPreview(); 
      } 
     } catch (IOException exception) {} 
    } 

    public void surfaceDestroyed(SurfaceHolder holder) { 
     if (mCamera != null) { 
      mCamera.stopPreview(); 
      mCamera.release(); 
     } 
    } 

    public void surfaceChanged(SurfaceHolder holder, int format, int width, int height) { 
     if (mHolder.getSurface() == null) { 
      return; 
     } 
     stopPreview(); 
     setCamera(mCamera); 
     startPreview(); 
     mCamera.startPreview(); 
    } 

    public void startPreview() { 
     try { 
      if (mCamera != null) { 
       mCamera.setPreviewDisplay(mHolder); 
       mCamera.startPreview(); 
      } 
     } catch (Exception e) {} 
    } 

    public void stopPreview() { 
     try { 
      if (mCamera != null) 
       mCamera.stopPreview(); 
     } catch (Exception e) {} 
    } 
} 

Ожидаемый результат на изображении с левой стороны. Полученный результат находится на изображении с правой стороны. Предварительный просмотр камеры растянут. Как исправить правильное соотношение сторон камеры? enter image description here

+0

любые исправления для этого? @Dylan – ralphgabb

+0

Если я правильно понимаю, ** Предварительный просмотр. onLayout() ** никогда не вызывается, потому что это представление не добавляется в представление контента, среди других проблем. Ваш класс должен «расширять SurfaceView» и накачиваться во время выполнения, потому что вы не знаете пропорции камеры перед тем, как начать. –

ответ

0

Исходный код для CAMERA1 и Android 4-5:

@Override 
protected void onResume() { 
    super.onResume(); 
    camera = Camera.open(CAMERA_ID); 
    setPreviewSize(); 
} 

@Override 
protected void onPause() { 
    super.onPause(); 
    if (camera != null) 
     camera.release(); 
    camera = null; 
} 
... 
void setPreviewSize() { 
    // получаем размеры экрана 
    Display display = getWindowManager().getDefaultDisplay(); 
    int w1 = display.getWidth(); 
    int h1 = display.getHeight(); 
    boolean widthIsMax = display.getWidth() > display.getHeight(); 

    // определяем размеры превью камеры 
    Camera.Size size = camera.getParameters().getPreviewSize(); 

    RectF rectDisplay = new RectF(); 
    RectF rectPreview = new RectF(); 

    // RectF экрана, соотвествует размерам экрана 
    rectDisplay.set(0, 0, w1, h1); 

    // подготовка матрицы преобразования 
    Matrix matrix = new Matrix(); 
    // RectF первью 
    if (widthIsMax) { 
     // превью в горизонтальной ориентации 
     rectPreview.set(0, 0, size.width, size.height); 

     // если экран будет "втиснут" в превью (третий вариант из урока) 
     matrix.setRectToRect(rectPreview, rectDisplay, 
       Matrix.ScaleToFit.START); 
    } else { 
     // превью в вертикальной ориентации 
     rectPreview.set(0, 0, size.height, size.width); 

     // если превью будет "втиснут" в экран (второй вариант из урока) 
     matrix.setRectToRect(rectPreview, rectDisplay, 
       Matrix.ScaleToFit.START); 
    } 

    // преобразование 
    matrix.mapRect(rectPreview); 

    // установка размеров surface из получившегося преобразования 
    h0 = (int) (rectPreview.bottom); 
    w0 = (int) (rectPreview.right); 

    surfaceView.getLayoutParams().height = h0; 
    surfaceView.getLayoutParams().width = w0; 
} 

См http://startandroid.ru/ru/uroki/vse-uroki-spiskom/264-urok-132-kamera-vyvod-izobrazhenija-na-ekran-obrabotka-povorota.html