您的位置:首页 > 移动开发 > Android开发

Android 直接控制摄像头并解决照片旋转90度的问题

2015-09-16 15:30 666 查看
问题背景:

大家好,我在安卓机拍照的过程中发现,使用原生相机拍照时,屏幕显示的画面范围比最后生成的照片要小。

下面给出具体的情况,请大家帮忙分析:

拍照时屏幕显示的画面:



实际照片内容:



可以看到,屏幕上呈现的画面只是照片的一部分,如示意图所示:



原生的拍照程序会有以上问题,需要通过camera API直接控制摄像头。

上面的问题只需要将surfaceView旋转90度就能解决,在代码中为: camera.setDisplayOrientation(90);

下面是源码:(参考《Android4高级编程》)

package com.example.haveimgfun;

import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;

import android.annotation.SuppressLint;
import android.app.Activity;
import android.os.Bundle;
import android.os.Environment;
import android.util.Log;
import android.view.SurfaceHolder;
import android.view.SurfaceView;
import android.view.View;
import android.view.View.OnClickListener;
import android.widget.Button;
import android.hardware.Camera;
import android.hardware.Camera.AutoFocusCallback;
import android.hardware.Camera.PictureCallback;
import android.hardware.Camera.ShutterCallback;

@SuppressLint("NewApi")
public class CameraActivity extends Activity implements SurfaceHolder.Callback{
	
	private Camera camera;
	
	@Override
	public void onCreate(Bundle savedInstanceState) {
		super.onCreate(savedInstanceState);
		setContentView(R.layout.activity_camera);
	    
		SurfaceView surface = (SurfaceView)findViewById(R.id.surfaceView);
		SurfaceHolder holder = surface.getHolder();
		holder.addCallback(this);
		holder.setType(SurfaceHolder.SURFACE_TYPE_PUSH_BUFFERS);
		holder.setFixedSize(400, 300);
		
		//Button to take picture
		Button snap = (Button)findViewById(R.id.buttonTakePicture);
		snap.setOnClickListener(new OnClickListener() {
			public void onClick(View v) {
		        takePicture();    
			}
		});
		
		//Button to auto focus
		Button autofocus = (Button)findViewById(R.id.buttonAutofocus);
		autofocus.setOnClickListener(new OnClickListener(){
			public void onClick(View v){
				doAutoFocus();
			}
		});
	}
	
	@Override
	public void surfaceChanged(SurfaceHolder arg0, int arg1, int arg2, int arg3) {
		// TODO Auto-generated method stub
		camera.cancelAutoFocus(); //release auto fucus 2如果要实现连续的自动对焦,这一句必须加上 
	}

	@Override
	public void surfaceCreated(SurfaceHolder holder) {
		// TODO Auto-generated method stub
		try {
		      camera.setPreviewDisplay(holder);
		      camera.startPreview();
		      camera.setDisplayOrientation(90);   //by me rotate 90
		      //camera.startFaceDetection();
		      // TODO Draw over the preview if required.
		} catch (IOException e) {
		      Log.d("TAG", e.getMessage());
		}
	}

	@Override
	public void surfaceDestroyed(SurfaceHolder arg0) {
		// TODO Auto-generated method stub
		camera.setPreviewCallback(null) ; //debug
		camera.stopPreview();
		camera.release();
		camera=null;
	}
	
	@Override
	protected void onPause() {
	    super.onPause();
	    //camera.release();
	}

	@Override
	protected void onResume() {
	  super.onResume();
	  camera = Camera.open();     
	  //get focus area number
	}
	
	//define shutterCallback
	ShutterCallback shutterCallback = new ShutterCallback() {
	    public void onShutter() {
	      // TODO Do something when the shutter closes.
	    }  
	};
	  
	  PictureCallback rawCallback = new PictureCallback() {
		  public void onPictureTaken(byte[] data, Camera camera) {
		  // TODO Do something with the image RAW data.
		  } 
	  };
	
	  //stroe the picture in format jpeg
	  PictureCallback jpegCallback = new PictureCallback() {
		    public void onPictureTaken(byte[] data, Camera camera) {
		      // Save the image JPEG data to the SD card
		      FileOutputStream outStream = null;
		      try {
		        String path = Environment.getExternalStorageDirectory() + 
		                      "/test.jpg";
		        outStream = new FileOutputStream(path);
		        outStream.write(data);
		        outStream.close();
		        finish();   //finish current activity
		      } catch (FileNotFoundException e) {
		        Log.e("TAG", "File Note Found", e);
		      } catch (IOException e) {
		        Log.e("TAG", "IO Exception", e);
		      }
		    }
	  };
	  
	//handle button snap
	private void takePicture() {
		camera.takePicture(shutterCallback, rawCallback, jpegCallback);
	}

	//handle button auto focus
	private void doAutoFocus(){
		Camera.Parameters parameters = camera.getParameters();
		if(parameters.getSupportedFocusModes().contains(Camera.Parameters.FOCUS_MODE_CONTINUOUS_PICTURE)){
			parameters.setFocusMode(Camera.Parameters.FOCUS_MODE_CONTINUOUS_PICTURE);
			camera.autoFocus(new AutoFocusCallback(){
				public void onAutoFocus(boolean success, Camera camera){
					Log.i("TAG","AutoFocus:"+(success?"Succeeded":"Failed"));
				}
			});
		}
	}
}


</pre><pre>
xml:

<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="fill_parent"
    android:layout_height="fill_parent">

    <LinearLayout
        android:layout_alignParentTop="true"
        android:id="@+id/linearLayout1"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:orientation="horizontal" >
        <Button
        android:id="@+id/buttonAutofocus"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="Autofocus" />

    <Button
        android:id="@+id/buttonFaces"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="Faces" />
    
        <Button
        android:id="@+id/buttonFocusDistances"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="Distances" />
        
                <Button
        android:id="@+id/buttonTakePicture"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="Snap" />
                
                        <Button
        android:id="@+id/buttonExif"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="Exif" />
    </LinearLayout>
    
    <SurfaceView
        android:layout_below="@id/linearLayout1"
        android:id="@+id/surfaceView"
        android:layout_width="match_parent"
        android:layout_height="match_parent" />

</RelativeLayout>


之前遇到一个bug:

当我使用下面代码时:

public void surfaceDestroyed(SurfaceHolder holder) {
    //camera.stopFaceDetection();
    camera.stopPreview();
  }
  
  @Override
  protected void onPause() {
    super.onPause();
    camera.release();
  }
会报Method called after release()的bug

将代码改为下面所示则没有bug。可能是因为camera.release()的时间问题,若放在onPause()中,销毁之后还会用到camera。有时间可以仔细分析。

@Override
     public void surfaceDestroyed(SurfaceHolder arg0) {
            // TODO Auto-generated method stub
            camera.setPreviewCallback( null) ; //debug
            camera.stopPreview();
            camera.release();
            camera= null;
     }
     
     @Override
     protected void onPause() {
         super.onPause();
         //camera.release();
     }
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: