自定义摄像机应用实现之预览界面展示

本文主要是Apress.Pro.Android.Media.Dec.2010书籍的读书笔记,加上自己的一些理解

要创建一个自定义的摄像机应用,就需要调用androidCamera这个类。这个类可以帮助我们调用手机的内置摄像头,并通过设置各种参数达到我们的要求,比如显示的大小,曝光度等。

摄像头权限

为了能够调用Camera类捕捉画面,我们需要在AndroidManifest.xml文件中指定权限

<uses-permission android:name="android.permission.CAMERA" />

预览界面

在布局中利用surfaceView控件来展示摄像头界面,以下是一个基本的布局(surfaceView由于可以直接从内存或者DMA等硬件接口取得图像数据,因此是个非常重要的绘图容器)

 

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="
http://schemas.android.com/apk/res/android"
android:orientation="vertical"
android:layout_width="fill_parent"
android:layout_height="fill_parent">
  <SurfaceView android:id="@+id/CameraView" android:layout_width="fill_parent"
    android:layout_height="fill_parent"></SurfaceView>
</LinearLayout> 

 

在代码中利用surfaceholder来监听摄像头的创建、销毁、改变的事件

创建预览界面分一下几个步骤

1、在surfaceCreated中获取Camera对象

2、设置camera的预览监听

3、启动摄像头预览

4、在surfaceDestroyed中当控件销毁时,关闭摄像头预览,并释放资源

package com.camerademo;

import java.util.Iterator;
import java.util.List;

import android.app.Activity;
import android.content.pm.ActivityInfo;
import android.content.res.Configuration;
import android.hardware.Camera;
import android.os.Bundle;
import android.util.Log;
import android.view.SurfaceHolder;
import android.view.SurfaceView;
import android.view.ViewGroup.LayoutParams;
import android.widget.LinearLayout;

public class Main extends Activity implements SurfaceHolder.Callback{

 SurfaceView cameraView;
 SurfaceHolder surfaceHolder;
 Camera camera;
 
 public static final int LARGEST_WIDTH = 300;
 public static final int LARGEST_HEIGHT = 300;
 
 @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE);
        setContentView(R.layout.main);
        cameraView = (SurfaceView) this.findViewById(R.id.CameraView);
        surfaceHolder = cameraView.getHolder();
        surfaceHolder.setType(SurfaceHolder.SURFACE_TYPE_PUSH_BUFFERS);
        surfaceHolder.addCallback(this);
        System.out.println("oncreate");
    }

 /* (non-Javadoc)
  * @see android.app.Activity#onStart()
  */
 @Override
 protected void onStart() {
  super.onStart();
  System.out.println("onstart");
 }
 
 @Override
 public void surfaceChanged(SurfaceHolder arg0, int arg1, int arg2, int arg3) {
  System.out.println("surfaceChanged");
 }

 @Override
 public void surfaceCreated(SurfaceHolder holder) {
  System.out.println("surfaceCreated");
  camera = Camera.open();//
获取Camera对象
  try{
   camera.setPreviewDisplay(holder);//
设置预览监听
   Camera.Parameters parameters = camera.getParameters();
   if(this.getResources().getConfiguration().orientation!=Configuration.ORIENTATION_LANDSCAPE){
    parameters.set("orientation", "portrait");
    camera.setDisplayOrientation(90);//
针对android2.2和之前的版本
    parameters.setRotation(90);//去掉android2.0和之前的版本
   }else{
    parameters.set("orientation", "landscape");
    camera.setDisplayOrientation(0);
    parameters.setRotation(0);
   }
   camera.setParameters(parameters);
   
   int bestWidth = 0;
   int bestHeight = 0;
   List<Camera.Size> previewSizes = parameters.getSupportedPictureSizes();
   if(previewSizes.size()>1){
    Iterator<Camera.Size> cei = previewSizes.iterator();
    while(cei.hasNext()){
     Camera.Size aSize = cei.next();
     System.out.println(aSize.width+","+aSize.height);
     if(aSize.width>bestWidth  && aSize.width<=LARGEST_WIDTH
       && aSize.height>bestHeight && aSize.height<=LARGEST_HEIGHT){
      bestWidth = aSize.width;
      bestHeight = aSize.height;
     }
     if(bestHeight!=0 && bestWidth != 0){
      Log.v("SNAPSHOT", "Using"+bestWidth+"x"+bestHeight);
      parameters.setPreviewSize(bestWidth, bestHeight);
      cameraView.setLayoutParams(new LinearLayout.LayoutParams(bestWidth,bestHeight));
     }
    }
   }

    camera.startPreview();//启动摄像头预览

  }catch(Exception e){
   camera.release();//
如果在设置摄像头的时候出现异常,在这里释放资源
  }
   }

 @Override
 public void surfaceDestroyed(SurfaceHolder arg0) {//
当要销毁时,先停止预览,并释放资源
  System.out.println("surfaceDestroyed");
  camera.stopPreview();
  camera.release();
 }
}

 

这里要注意下,手机的摄像头资源是唯一的,如果你不需要再使用时,应及时释放其资源,不然会导致其应用程序无法调用摄像头的。

所以在上上面的代码中,当控件要销毁时surfacedestroyed方法中,释放了资源。在设置设置摄像头预览监听时有可能发生io异常所以用try/catch包裹camera.setPreviewDisplay(holder);方法,如果出现异常也释放资源。
刚才指介绍了创建预览界面,那么如何创建我们要求的预览界面呢,比如大小什么的,关键就在surfaccreated方法中设置camera的属性了。

1、预览界面的横竖屏展示

在进行摄像头的相关开发时,最常遇到的就是如何设置摄像头的正确方向是横向的或是竖向的。可以通过设置carmera的属性的来实现,由于官方并没有提供统一的方法进行设置,所以不同版本的设置方法都不太一样。

camera.setPreviewDisplay(holder);
   Camera.Parameters parameters = camera.getParameters();
   if(this.getResources().getConfiguration().orientation!=Configuration.ORIENTATION_LANDSCAPE){
    parameters.set("orientation", "portrait");
    camera.setDisplayOrientation(90);//
针对android2.2和之前的版本
    parameters.setRotation(90);//去掉android2.0和之前的版本
   }else{
    parameters.set("orientation", "landscape");
    camera.setDisplayOrientation(0);
    parameters.setRotation(0);
   }
   camera.setParameters(parameters);


先判断当前的界面是横向还是竖向的,针对2.2以上的版本可以设置

parameters.set("orientation", "portrait") parameters.set("orientation", "landscape");
2.2
和之前的版本可以设置

camera.setDisplayOrientation(90)camera.setDisplayOrientation(0)

2.0和之前的可以设置

parameters.setRotation(90) parameters.setRotation(0)

 

2、预览界面的效果设置

android api中可选择的颜色效果有许多种:

EFFECT_NONE 无效果
EFFECT_MONO 黑白效果
EFFECT_NEGATIVE 负面效果
EFFECT_SOLARIZE 曝光效果
EFFECT_SEPIA Sephia效果
EFFECT_POSTERIZE 多色调分色印效果

EFFECT_WHITEBOARD 白板效果
EFFECT_BLACKBOARD 黑板效果
EFFECT_AQUA 浅绿色效果

这么多的效果专业名词对于我这种非图像专业的还是看不懂啊,只有没有都试下才明白,不过要注意的是这么多效果并不是没款手机都支持的,因此我们在调用的时候应当先获取该手机支持的效果类型,再来设置,这些效果在不同的手机上还不太一样,比如在我的G7上这样设置都没有效果。如下:

 List<String> colorEffects = parameters.getSupportedColorEffects();
  Iterator<String> cei = colorEffects.iterator();
  while(cei.hasNext()){
   String currentEffect = cei.next();
   System.out.println("Checking:"+currentEffect);
   if(currentEffect.equals(Camera.Parameters.EFFECT_SOLARIZE)){
    parameters.setColorEffect(Camera.Parameters.EFFECT_SOLARIZE);//
曝光效果
    break;
   }
  }

 

3、预览界面的大小设置

预览界面大小的设置和效果设置类似,你也必须先判断手机支持哪几种比例的大小在进行设置,不然获得的图像会变形的。如下:

int bestWidth = 0;
  int bestHeight = 0;
  List<Camera.Size> previewSizes = parameters.getSupportedPictureSizes();
  if(previewSizes.size()>1){
   Iterator<Camera.Size> cei = previewSizes.iterator();
   while(cei.hasNext()){
    Camera.Size aSize = cei.next();
    System.out.println(aSize.width+","+aSize.height);
    if(aSize.width>bestWidth  && aSize.width<=LARGEST_WIDTH
      && aSize.height>bestHeight && aSize.height<=LARGEST_HEIGHT){
     bestWidth = aSize.width;
     bestHeight = aSize.height;
    }
    if(bestHeight!=0 && bestWidth != 0){
     Log.v("SNAPSHOT", "Using"+bestWidth+"x"+bestHeight);
     parameters.setPreviewSize(bestWidth, bestHeight);
     cameraView.setLayoutParams(new LinearLayout.LayoutParams(bestWidth,bestHeight));
    }
   }
  }

 

LARGEST_WIDTH LARGEST_HEIGHT 为我们设置的预期的预览界面的大小比如300*300

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值