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) {} 
    } 
} 

입니다 왼쪽 이미지에. 얻은 결과는 오른쪽 이미지에 있습니다. 카메라 미리보기가 늘어납니다. 카메라 미리보기의 올바른 종횡비를 수정하는 방법은 무엇입니까? 카메라 1 및 안드로이드 4-5 enter image description here

+0

어떤 수정을 참조하십시오? @Dylan – ralphgabb

+0

정확하게 이해하면 ** 미리보기. onLayout() **은이 뷰가 컨텐츠 뷰에 ​​추가되지 않았기 때문에 호출되지 않습니다. 당신의 클래스는'SurfaceView'를 확장해야하고 런타임 전에 팽창 될 것입니다, 왜냐하면 당신은 그것이 시작되기 전에 카메라의 종횡비를 알지 못하기 때문입니다. –

답변

0

소스 코드 :

@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