android相机如何只显示处理后的图像以及这里onPreviewFrame不被调用的原因

前段时间,一直想写一个关于android相机的程序,实现如下功能:程序通过摄像机实时获取图像,但是不直接显示获取的图像,而是显示处理过后的图像。

就这个如何不显示处理前只显示处理后的图像,纠结了很久,网上搜索了很多,对于这个问题,网上的信息都是重复无用的,根本无法解决。接下来我详细的说明遇见的问题和解决方法。

一开始程序见程序段1,这么写的话,屏幕上面只会显示摄像头获取到的图片,处理过后的图片完全不会显示,后面要是强行的向这个surfaceholder控制的surfaceview来输出图片,程序会报错。

public void surfaceCreated(SurfaceHolder holder) {
		//开启相机
		camera=Camera.open();
		try
		{			
			camera.setPreviewDisplay(surfaceholder);
			ShowMessage("开启相机成功");//toast提示
		}
		catch(Exception e)
		{
			ShowMessage("开启相机失败");//toast提示
			camera.release();
			camera=null;
		}
	}//程序段1
后来发现可能是camera.setPreviewDisplay(surfaceholder)这句有问题,相机一直在用这个holder像surfaceview输出图像,后面程序中再使用surfaceholder来绘制新的图片,就会冲突,然后报错。

也试过用两个重叠的surfaceview来实现,一个给相机用,一个给处理后的图片用,通过程序控制将其中给相机用的那个隐藏掉,但是这么做行不通,后面再说为什么不行。也尝试过camera.setPreviewDisplay(null);这么写的话,在模拟器中是可以运行的,但是到了真机上面就不行了。在真机上,这两种办法都不会调用 onPreviewFrame(byte[] data, Camera arg1) ,查资料发现,android的相机获取的图片必须有一个surfaceview来显示,否则就不会调用 onPreviewFrame(byte[] data, Camera arg1) 方法。看到这里都会都会觉得Android好神烦。

在较新的apk版本中可以用camera.setPreviewTexture(surfacetexture)来替代camera.setPreviewDisplay(surfaceholder)。camera.setPreviewTexture(surfacetexture)这个方法允许相机获取的图片在一个隐藏的surfacetexture上显示,这么一来,便可以实现一开始提到的那个功能。

下面是一个基本的框架:

package com.example.atest01;

import java.io.ByteArrayOutputStream;
import java.io.IOException;

import android.graphics.Bitmap;
import android.graphics.Bitmap.Config;
import android.graphics.BitmapFactory;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.ImageFormat;
import android.graphics.Paint;
import android.graphics.Rect;
import android.graphics.SurfaceTexture;
import android.graphics.YuvImage;
import android.graphics.drawable.BitmapDrawable;
import android.hardware.Camera;
import android.hardware.Camera.PreviewCallback;
import android.os.Bundle;
import android.app.Activity;
import android.util.DisplayMetrics;
import android.view.Display;
import android.view.Menu;
import android.view.SurfaceHolder;
import android.view.SurfaceView;
import android.view.View;
import android.view.Window;
import android.view.WindowManager;
import android.widget.Toast;

public class MainActivity extends Activity implements SurfaceHolder.Callback {
	
	SurfaceHolder surfaceholder;
	SurfaceView surfaceview;
	Canvas canvas;
	Camera camera;
	SurfaceTexture surfacetexture;
	int counter=0;
	int width,height,sum;
	Bitmap img1;
	
	@Override
	protected void onCreate(Bundle savedInstanceState) {
		super.onCreate(savedInstanceState);
		requestWindowFeature(Window.FEATURE_NO_TITLE);
		getWindow().setFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN, WindowManager.LayoutParams.FLAG_FULLSCREEN);
		setContentView(R.layout.activity_main);
		
		img1=((BitmapDrawable)getResources().getDrawable(R.drawable.ic_launcher)).getBitmap();
		surfaceview=(SurfaceView)findViewById(R.id.sv1);
		//获得控件  添加surfaceholder
		surfaceholder=surfaceview.getHolder();
		surfaceholder.addCallback(this);
		surfacetexture=new SurfaceTexture(10);
		//surfaceholder.setType(SurfaceHolder.SURFACE_TYPE_PUSH_BUFFERS);
		//获得屏幕的长宽像素点数,这边的长宽像素要修改,不然会报错,
				//因为有的机型的长宽像素点数,不是setpreviewSize支持的长宽。
		DisplayMetrics dm=new DisplayMetrics();
		getWindowManager().getDefaultDisplay().getMetrics(dm);
		width=dm.widthPixels;
		height=dm.heightPixels;
		sum=width*height;
		/*/显示屏幕的长宽像素点数
		String s=Integer.toString(width)+"\n"+Integer.toString(height);
		ShowMessage(s);//*/		
	}

	@Override
	public boolean onCreateOptionsMenu(Menu menu) {
		
		getMenuInflater().inflate(R.menu.main, menu);
		return true;
	}
	
	public void ShowMessage(String text)
	{
		Toast.makeText(this, text, Toast.LENGTH_SHORT).show();
	}

	@Override
	public void surfaceChanged(SurfaceHolder arg0, int arg1, int arg2, int arg3) {
		Camera.Parameters parameters=camera.getParameters();	
		parameters.setPictureSize(width, height);
		parameters.setPreviewSize(width, height);
		
		previewcallback pre = new previewcallback();//建立预览回调对象
		camera.setPreviewCallback(pre);
        //camera.setPreviewCallback(pre); //设置预览回调对象
		camera.setParameters(parameters);	
		
		camera.startPreview();
		ShowMessage("开启相机成功22323");
		counter++;
		ShowMessage(Integer.toString(counter));
	}

	@Override
	public void surfaceCreated(SurfaceHolder holder) {
		//开启相机
		camera=Camera.open();
		try
		{			
			camera.setPreviewTexture(surfacetexture);
			ShowMessage("开启相机成功");
		}
		catch(Exception e)
		{
			ShowMessage("开启相机失败");
			camera.release();
			camera=null;
		}

	}

	@Override
	public void surfaceDestroyed(SurfaceHolder arg0) {
		
		camera.stopPreview();
		camera.release();
		camera=null;
	}
	
	class previewcallback implements Camera.PreviewCallback
	{
		byte tmp;
		public previewcallback()
		{
			
		}
		
		@Override
		public void onPreviewFrame(byte[] data, Camera arg1) {
			// TODO Auto-generated method stub
			//ShowMessage("开启相机成功qwe");
			try
			{
				ShowMessage("here go");
			}
			catch(Exception e)
			{
				ShowMessage("Err 001");
				e.printStackTrace();
			}
			//*///此代码显示出每次都在调用这个onPreviewFrame方法		
		}	
	}
}


你可能感兴趣的:(android)