- 文安大众论坛 -

 找回密码
 注册

QQ登录

只需一步,快速开始

广告位招租
查看: 946|回复: 0

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

[复制链接]

该用户从未签到

发表于 2014-5-13 06:26:39 | 显示全部楼层 |阅读模式
    本文主要是Apress.Pro.Android.Media.Dec.2010书籍的读书笔记,加上自己的一些理解
    要创建一个自定义的摄像机应用,就需要调用android的Camera这个类。这个类可以帮助我们调用手机的内置摄像头,并通过设置各种参数达到我们的要求,比如显示的大小,曝光度等。
    摄像头权限
    为了能够调用Camera类捕捉画面,我们需要在AndroidManifest.xml文件中指定权限
    <uses-permission android:name="android.permission.CAMERA" />
    预览界面
    在布局中利用surfaceView控件来展示摄像头界面,以下是一个基本的布局(surfaceView由于可以直接从内存或者DMA等硬件接口取得图像数据,因此是个非常重要的绘图容器)
    <?xml veion="1.0" encoding="utf-8"?>
    <LinearLayout xml:andro
    androidrientation="vertical"
    android:layout_
    android:layout_>
    <SurfaceView android: android:layout_
    android:layout_></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 savedItanceState) {
    super.onCreate(savedItanceState);
    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("otart");
    }
    @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.Paramete paramete = camera.getParamete();
     if(this.getResources().getConfiguration().orientation!=Configuration.ORIENTATION_LANDSCAPE){
    paramete.set("orientation", "portrait");
    camera.setDisplayOrientation(90);//针对android2.2和之前的版本
    paramete.setRotation(90);//去掉android2.0和之前的版本
     }else{
    paramete.set("orientation", "landscape");
    camera.setDisplayOrientation(0);
    paramete.setRotation(0);
     }
     camera.setParamete(paramete);
     int bestWidth = 0;
     int bestHeight = 0;
     List<Camera.Size> previewSizes = paramete.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);
    paramete.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.Paramete paramete = camera.getParamete();
     if(this.getResources().getConfiguration().orientation!=Configuration.ORIENTATION_LANDSCAPE){
    paramete.set("orientation", "portrait");
    camera.setDisplayOrientation(90);//针对android2.2和之前的版本
    paramete.setRotation(90);//去掉android2.0和之前的版本
     }else{
    paramete.set("orientation", "landscape");
    camera.setDisplayOrientation(0);
    paramete.setRotation(0);
     }
     camera.setParamete(paramete);
    先判断当前的界面是横向还是竖向的,针对2.2以上的版本可以设置paramete.set("orientation", "portrait")或 paramete.set("orientation", "landscape");
    2.2和之前的版本可以设置camera.setDisplayOrientation(90)和camera.setDisplayOrientation(0)2.0和之前的可以设置paramete.setRotation(90) 和paramete.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 = paramete.getSupportedColorEffects();
    Iterator<String> cei = colorEffects.iterator();
    while(cei.hasNext()){
     String currentEffect = cei.next();
     System.out.println("Checking:" currentEffect);
     if(currentEffect.equals(Camera.Paramete.EFFECT_SOLARIZE)){
    paramete.setColorEffect(Camera.Paramete.EFFECT_SOLARIZE);//曝光效果
    break;
     }
    }
    3、预览界面的大小设置预览界面大小的设置和效果设置类似,你也必须先判断手机支持哪几种比例的大小在进行设置,不然获得的图像会变形的。如下:
    int bestWidth = 0;
    int bestHeight = 0;
    List<Camera.Size> previewSizes = paramete.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);
    paramete.setPreviewSize(bestWidth, bestHeight);
    cameraView.setLayoutParams(new LinearLayout.LayoutParams(bestWidth,bestHeight));
    }
     }
    }
    LARGEST_WIDTH 和 LARGEST_HEIGHT 为我们设置的预期的预览界面的大小比如300*300。
您需要登录后才可以回帖 登录 | 注册

本版积分规则

删帖申请|小黑屋|手机版|Archiver|Comsenz Inc. ( 冀ICP备12019373号-1 ) 法律顾问:常全根律师

GMT+8, 2024-11-11 06:19 , Processed in 5.601729 second(s), 21 queries .

Powered by Discuz! X3.4

© 2001-2023 Discuz! Team.

快速回复 返回顶部 返回列表