• Android Camera开发:给摄像头预览界面加个ZoomBar(附完整代码下载)


    源码:http://files.cnblogs.com/android100/StandardCamera2013-10-18.zip

    废话不说了,就是加个seekbar,拖动的话能够调节焦距,让画面变大或缩小。下面是核心程序:

    一,camera的布局文件

    1. <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"  
    2.     xmlns:tools="http://schemas.android.com/tools"  
    3.     android:layout_width="fill_parent"  
    4.     android:layout_height="fill_parent"  
    5.     android:orientation="vertical" >  
    6.   
    7.     <TextView  
    8.         android:layout_width="wrap_content"  
    9.         android:layout_height="wrap_content"  
    10.         android:text="@string/BestWish"  
    11.         tools:context=".StandardCamera" />  
    12.   
    13.     <RelativeLayout  
    14.         android:layout_width="wrap_content"  
    15.         android:layout_height="wrap_content" >  
    16.   
    17.         <FrameLayout  
    18.             android:layout_width="wrap_content"  
    19.             android:layout_height="wrap_content" >  
    20.   
    21.             <SurfaceView  
    22.                 android:id="@+id/previewSV"  
    23.                 android:layout_width="fill_parent"  
    24.                 android:layout_height="wrap_content" />  
    25.         </FrameLayout>  
    26.           
    27.         <LinearLayout  
    28.         android:id="@+id/zoomLayout"  
    29.         android:layout_width="wrap_content"  
    30.         android:layout_height="40dp"  
    31.         android:layout_centerInParent="true"  
    32.         android:layout_centerHorizontal="true"                  
    33.         android:orientation="horizontal" >  
    34.   
    35.         <TextView  
    36.             android:id="@+id/textView1"  
    37.             android:layout_width="wrap_content"  
    38.             android:layout_height="wrap_content"  
    39.             android:text="-"  
    40.             android:textColor="#ffffff"   
    41.             android:textSize="30dip"/>  
    42.   
    43.         <SeekBar  
    44.             android:id="@+id/seekbar_zoom"  
    45.             android:layout_width="300dp"  
    46.             android:layout_height="wrap_content"  
    47.             android:layout_gravity="center_vertical"  
    48.            android:progressDrawable="@drawable/seekbar_style"  
    49.             android:thumb="@drawable/ic_launcher"  
    50.             android:thumbOffset="0dp" />  
    51.   
    52.         <TextView  
    53.             android:id="@+id/textView2"  
    54.             android:layout_width="wrap_content"  
    55.             android:layout_height="wrap_content"  
    56.              android:text="+"  
    57.             android:textColor="#ffffff"  
    58.             android:textSize="30dip" />  
    59.     </LinearLayout>  
    60.     </RelativeLayout>  
    61.   
    62.       
    63.   
    64.     <ImageButton  
    65.         android:id="@+id/photoImgBtn"  
    66.         android:layout_width="wrap_content"  
    67.         android:layout_height="wrap_content"  
    68.         android:layout_gravity="center"  
    69.         android:background="@drawable/photo_img_btn" />  
    70.   
    71. </LinearLayout>  


    其中里面嵌套的LinearLayout就是那个ZoomBar,最外面我用了相对布局,发现相对布局用起来还是很好用的。为了方便以后扩展,Camera的SurfaceView用的帧布局。注意SeekBar的几个参数,其中的progressDrawable是指那个横条的形状,可以直接用个图片,也可以写个xml文件。这里用的是xml,当然用图片很简单。seekbar_style.xml文件如下:

    1. <?xml version="1.0" encoding="UTF-8"?>     
    2. <layer-list xmlns:android="http://schemas.android.com/apk/res/android">     
    3.   <item android:id="@android:id/background">    
    4.          <shape>    
    5.              <corners android:radius="5dip" />    
    6.              <gradient    
    7.                      android:startColor="#ff9d9e9d"    
    8.                      android:centerColor="#ff5a5d5a"    
    9.                      android:centerY="0.75"    
    10.                      android:endColor="#ff747674"    
    11.                      android:angle="270"    
    12.              />    
    13.          </shape>    
    14.      </item>    
    15. </layer-list>     


    下面的android:thumb是滑动的那个手柄,本来我是写了一个xml文件,名字为thumb.xml如下:

    1. <?xml version="1.0" encoding="UTF-8"?>  
    2. <selector xmlns:android="http://schemas.android.com/apk/res/android">  
    3.   
    4.     <!-- 按下状态 -->  
    5.     <item android:state_focused="true" android:state_pressed="true"><shape android:shape="oval">  
    6.             <gradient android:angle="0" android:centerColor="#FF00FF00" android:endColor="#000000" android:gradientRadius="8" android:startColor="#FFFF0000" android:type="radial" />  
    7.   
    8.             <size android:height="20dip" android:width="20dip"></size>  
    9.         </shape></item>  
    10.   
    11.   
    12. </selector>  

    无奈啥也显示不出来,索性直接找了个粗糙的图片,见谅哈!

    二,整个程序的主代码:

    1. package yan.guoqi.camera;  
    2. import java.io.BufferedOutputStream;  
    3. import java.io.File;  
    4. import java.io.FileOutputStream;  
    5. import java.io.IOException;  
    6. import java.util.List;  
    7.   
    8. import yan.guoqi.rectphoto.R;  
    9. import android.app.Activity;  
    10. import android.content.Context;  
    11. import android.graphics.Bitmap;  
    12. import android.graphics.BitmapFactory;  
    13. import android.graphics.ColorMatrixColorFilter;  
    14. import android.graphics.Matrix;  
    15. import android.graphics.PixelFormat;  
    16. import android.hardware.Camera;  
    17. import android.hardware.Camera.AutoFocusCallback;  
    18. import android.hardware.Camera.Parameters;  
    19. import android.hardware.Camera.PictureCallback;  
    20. import android.hardware.Camera.PreviewCallback;  
    21. import android.hardware.Camera.ShutterCallback;  
    22. import android.os.Bundle;  
    23. import android.util.Log;  
    24. import android.view.Display;  
    25. import android.view.MotionEvent;  
    26. import android.view.SurfaceHolder;  
    27. import android.view.SurfaceView;  
    28. import android.view.View;  
    29. import android.view.View.OnClickListener;  
    30. import android.view.View.OnTouchListener;  
    31. import android.view.ViewGroup.LayoutParams;  
    32. import android.view.Window;  
    33. import android.view.WindowManager;  
    34. import android.widget.ImageButton;  
    35. import android.widget.SeekBar;  
    36. import android.widget.SeekBar.OnSeekBarChangeListener;  
    37.   
    38. public class StandardCamera extends Activity implements SurfaceHolder.Callback, PreviewCallback{  
    39.     private static final String tag="StandardCamera";  
    40.     private boolean isPreview = false;  
    41.     private SurfaceView mPreviewSV = null//棰勮�SurfaceView  
    42.     private SurfaceHolder mySurfaceHolder = null;  
    43.     private ImageButton mPhotoImgBtn = null;  
    44.     private Camera myCamera = null;  
    45.     private Bitmap mBitmap = null;  
    46.     private AutoFocusCallback myAutoFocusCallback = null;  
    47.     boolean flag = true;  
    48.       
    49.     private SeekBar mZoomBar = null;  
    50.   
    51.     @Override  
    52.     public void onCreate(Bundle savedInstanceState) {  
    53.         super.onCreate(savedInstanceState);  
    54.         requestWindowFeature(Window.FEATURE_NO_TITLE);  
    55.         int flag = WindowManager.LayoutParams.FLAG_FULLSCREEN;  
    56.         Window myWindow = this.getWindow();  
    57.         myWindow.setFlags(flag, flag);  
    58.   
    59.         setContentView(R.layout.activity_rect_photo);  
    60.   
    61.         initView();  
    62.         mySurfaceHolder = mPreviewSV.getHolder();  
    63.         mySurfaceHolder.setFormat(PixelFormat.TRANSLUCENT);  
    64.         mySurfaceHolder.addCallback(this);  
    65.         mySurfaceHolder.setType(SurfaceHolder.SURFACE_TYPE_PUSH_BUFFERS);  
    66.   
    67.   
    68.         myAutoFocusCallback = new AutoFocusCallback() {  
    69.   
    70.             public void onAutoFocus(boolean success, Camera camera) {  
    71.                 // TODO Auto-generated method stub  
    72.                 if(success)  
    73.                 {  
    74.                     Log.i(tag, "myAutoFocusCallback: success...");  
    75.   
    76.   
    77.                 }  
    78.                 else  
    79.                 {  
    80.                     Log.i(tag, "myAutoFocusCallback: 澶辫触浜�?.");  
    81.   
    82.                 }  
    83.   
    84.   
    85.             }  
    86.         };  
    87.           
    88.         //添加ZoomBar  
    89.         mZoomBar = (SeekBar)findViewById(R.id.seekbar_zoom);  
    90.         mZoomBar.setOnSeekBarChangeListener(new OnSeekBarChangeListener() {  
    91.               
    92.             public void onStopTrackingTouch(SeekBar seekBar) {  
    93.                 // TODO Auto-generated method stub  
    94.                   
    95.             }  
    96.               
    97.             public void onStartTrackingTouch(SeekBar seekBar) {  
    98.                 // TODO Auto-generated method stub  
    99.                   
    100.             }  
    101.               
    102.             public void onProgressChanged(SeekBar seekBar, int progress,  
    103.                     boolean fromUser) {  
    104.                 // TODO Auto-generated method stub  
    105.                 Parameters p = myCamera.getParameters();  
    106.                 p.setZoom(progress);  
    107.                 myCamera.setParameters(p);  
    108.             }  
    109.         });  
    110.   
    111.   
    112.   
    113.     }  
    114.   
    115.     public void initView(){  
    116.         mPreviewSV = (SurfaceView)findViewById(R.id.previewSV);  
    117.         WindowManager wm = (WindowManager)getSystemService(Context.WINDOW_SERVICE);  
    118.         Display display = wm.getDefaultDisplay();  
    119.         LayoutParams lpSV = mPreviewSV.getLayoutParams();  
    120.         lpSV.width = display.getWidth();  
    121.         lpSV.height = (int) ((float)display.getHeight()*0.75);  
    122.         mPreviewSV.setLayoutParams(lpSV);  
    123.   
    124.   
    125.             mPhotoImgBtn = (ImageButton)findViewById(R.id.photoImgBtn);  
    126.         LayoutParams lp = mPhotoImgBtn.getLayoutParams();  
    127.         lp.width = 240;  
    128.         lp.height = 240;          
    129.         mPhotoImgBtn.setLayoutParams(lp);                 
    130.         mPhotoImgBtn.setOnClickListener(new PhotoOnClickListener());  
    131.         mPhotoImgBtn.setOnTouchListener(new MyOnTouchListener());  
    132.     }  
    133.   
    134.     public void surfaceChanged(SurfaceHolder holder, int format, int width,int height)   
    135.     {  
    136.         // TODO Auto-generated method stub        
    137.         Log.i(tag, "SurfaceHolder.Callback:surfaceChanged!");  
    138.         initCamera();  
    139.   
    140.     }  
    141.   
    142.   
    143.     public void surfaceCreated(SurfaceHolder holder)   
    144.     {  
    145.         // TODO Auto-generated method stub        
    146.         myCamera = Camera.open();  
    147.         try {  
    148.             myCamera.setPreviewDisplay(mySurfaceHolder);  
    149.             Log.i(tag, "SurfaceHolder.Callback: surfaceCreated!");  
    150.         } catch (IOException e) {  
    151.             // TODO Auto-generated catch block  
    152.             if(null != myCamera){  
    153.                 myCamera.release();  
    154.                 myCamera = null;  
    155.             }  
    156.             e.printStackTrace();  
    157.         }  
    158.   
    159.   
    160.   
    161.     }  
    162.   
    163.   
    164.     public void surfaceDestroyed(SurfaceHolder holder)   
    165.   
    166.     {  
    167.         // TODO Auto-generated method stub  
    168.         Log.i(tag, "SurfaceHolder.Callback锛歋urface Destroyed");  
    169.         if(null != myCamera)  
    170.         {  
    171.             myCamera.setPreviewCallback(null);   
    172.   
    173.             myCamera.stopPreview();   
    174.             isPreview = false;   
    175.             myCamera.release();  
    176.             myCamera = null;       
    177.         }  
    178.   
    179.     }  
    180.   
    181.     public void initCamera(){  
    182.         if(isPreview){  
    183.             myCamera.stopPreview();  
    184.         }  
    185.         if(null != myCamera){             
    186.             Camera.Parameters myParam = myCamera.getParameters();  
    187.   
    188.   
    189.             myParam.setPictureFormat(PixelFormat.JPEG);//璁剧疆鎷嶇収鍚庡瓨鍌ㄧ殑鍥剧墖鏍煎紡  
    190.   
    191.               
    192.             //List<Size> pictureSizes = myParam.getSupportedPictureSizes();  
    193.                         //List<Size> previewSizes = myParam.getSupportedPreviewSizes();  
    194.             //          for(int i=0; i<pictureSizes.size(); i++){  
    195.             //              Size size = pictureSizes.get(i);  
    196.             //              Log.i(tag, "initCamera:pictureSizes: width = "+size.width+"height = "+size.height);  
    197.             //          }  
    198.             //          for(int i=0; i<previewSizes.size(); i++){  
    199.             //              Size size = previewSizes.get(i);  
    200.             //              Log.i(tag, "initCamera:鎽勫儚澶存敮鎸佺殑previewSizes: width = "+size.width+"height = "+size.height);  
    201.             //  
    202.             //          }  
    203.   
    204.   
    205.   
    206.             myParam.setPictureSize(1280960);  //  
    207.             myParam.setPreviewSize(960720);   //        
    208.             //myParam.set("rotation", 90);                
    209.             myCamera.setDisplayOrientation(90);    
    210.             List<String> focuseMode = (myParam.getSupportedFocusModes());  
    211.             for(int i=0; i<focuseMode.size(); i++){  
    212.                 Log.i(tag, focuseMode.get(i));  
    213.                 if(focuseMode.get(i).contains("continuous")){  
    214.                     myParam.setFocusMode(Camera.Parameters.FOCUS_MODE_CONTINUOUS_VIDEO);  
    215.                 }  
    216.                 else{  
    217.                     myParam.setFocusMode(Camera.Parameters.FOCUS_MODE_AUTO);  
    218.   
    219.                 }  
    220.             }  
    221.             //设置mZoomBar的最大值  
    222.             mZoomBar.setMax(myParam.getMaxZoom());  
    223.             myCamera.setParameters(myParam);              
    224.             myCamera.startPreview();  
    225.             myCamera.autoFocus(myAutoFocusCallback);  
    226.             isPreview = true;  
    227.         }  
    228.     }  
    229.   
    230.     ShutterCallback myShutterCallback = new ShutterCallback()   
    231.     {  
    232.   
    233.         public void onShutter() {  
    234.             // TODO Auto-generated method stub  
    235.             Log.i(tag, "myShutterCallback:onShutter...");  
    236.   
    237.         }  
    238.     };  
    239.     PictureCallback myRawCallback = new PictureCallback()   
    240.     {  
    241.   
    242.         public void onPictureTaken(byte[] data, Camera camera) {  
    243.             // TODO Auto-generated method stub  
    244.             Log.i(tag, "myRawCallback:onPictureTaken...");  
    245.   
    246.         }  
    247.     };  
    248.     PictureCallback myJpegCallback = new PictureCallback()   
    249.     {  
    250.   
    251.         public void onPictureTaken(byte[] data, Camera camera) {  
    252.             // TODO Auto-generated method stub  
    253.             Log.i(tag, "myJpegCallback:onPictureTaken...");  
    254.             if(null != data){  
    255.                 mBitmap = BitmapFactory.decodeByteArray(data, 0, data.length);//data鏄�瓧鑺傛暟鎹�紝灏嗗叾瑙f瀽鎴愪綅鍥�                myCamera.stopPreview();  
    256.                 isPreview = false;  
    257.             }  
    258.             Matrix matrix = new Matrix();  
    259.             matrix.postRotate((float)90.0);  
    260.             Bitmap rotaBitmap = Bitmap.createBitmap(mBitmap, 00, mBitmap.getWidth(), mBitmap.getHeight(), matrix, false);  
    261.             if(null != rotaBitmap)  
    262.             {  
    263.                 saveJpeg(rotaBitmap);  
    264.             }  
    265.   
    266.             myCamera.startPreview();  
    267.             isPreview = true;  
    268.         }  
    269.     };  
    270.     public class PhotoOnClickListener implements OnClickListener{  
    271.   
    272.         public void onClick(View v) {  
    273.             // TODO Auto-generated method stub  
    274.             if(isPreview && myCamera!=null){  
    275.                 myCamera.takePicture(myShutterCallback, null, myJpegCallback);    
    276.             }  
    277.   
    278.         }  
    279.   
    280.     }  
    281.   
    282.     public void saveJpeg(Bitmap bm){  
    283.         String savePath = "/mnt/sdcard/rectPhoto/";  
    284.         File folder = new File(savePath);  
    285.         if(!folder.exists()) {  
    286.             folder.mkdir();  
    287.         }  
    288.         long dataTake = System.currentTimeMillis();  
    289.         String jpegName = savePath + dataTake +".jpg";  
    290.         Log.i(tag, "saveJpeg:jpegName--" + jpegName);  
    291.         //File jpegFile = new File(jpegName);  
    292.         try {  
    293.             FileOutputStream fout = new FileOutputStream(jpegName);  
    294.             BufferedOutputStream bos = new BufferedOutputStream(fout);  
    295.   
    296.             //          Bitmap newBM = bm.createScaledBitmap(bm, 600, 800, false);  
    297.   
    298.             bm.compress(Bitmap.CompressFormat.JPEG, 100, bos);  
    299.             bos.flush();  
    300.             bos.close();  
    301.         } catch (IOException e) {  
    302.             // TODO Auto-generated catch block  
    303.   
    304.             e.printStackTrace();  
    305.         }  
    306.     }  
    307.   
    308.   
    309.     public class MyOnTouchListener implements OnTouchListener{  
    310.   
    311.         public final  float[] BT_SELECTED=new float[]  
    312.                 { 20002,  
    313.                 02002,  
    314.                 00202,  
    315.                 00010 };                  
    316.   
    317.         public final float[] BT_NOT_SELECTED=new float[]  
    318.                 { 10000,  
    319.                 01000,  
    320.                 00100,  
    321.                 00010 };  
    322.         public boolean onTouch(View v, MotionEvent event) {  
    323.             // TODO Auto-generated method stub  
    324.             if(event.getAction() == MotionEvent.ACTION_DOWN){  
    325.                 v.getBackground().setColorFilter(new ColorMatrixColorFilter(BT_SELECTED));  
    326.                 v.setBackgroundDrawable(v.getBackground());  
    327.             }  
    328.             else if(event.getAction() == MotionEvent.ACTION_UP){  
    329.                 v.getBackground().setColorFilter(new ColorMatrixColorFilter(BT_NOT_SELECTED));  
    330.                 v.setBackgroundDrawable(v.getBackground());  
    331.   
    332.             }  
    333.             return false;  
    334.         }  
    335.   
    336.     }  
    337.   
    338.     @Override  
    339.     public void onBackPressed()  
    340.     {  
    341.         // TODO Auto-generated method stub  
    342.         super.onBackPressed();  
    343.         StandardCamera.this.finish();  
    344.     }  
    345.   
    346.   
    347.   
    348.     class UpdateThread implements Runnable{  
    349.   
    350.         public void run() {  
    351.             // TODO Auto-generated method stub  
    352.             while(flag){  
    353.                 if(myCamera!=null && isPreview)  
    354.                     myCamera.autoFocus(myAutoFocusCallback); //鑷�姩鑱氱劍  
    355.                 myCamera.setOneShotPreviewCallback(StandardCamera.this); //onPreviewFrame閲屼細鎺ュ彈鍒版暟鎹�?           myCamera.stopPreview(); //鍋滄�棰勮�  
    356.                 flag = false;  
    357.   
    358.                 try {  
    359.                     Thread.sleep(1000);  
    360.                 } catch (InterruptedException e) {  
    361.                     // TODO Auto-generated catch block  
    362.                     e.printStackTrace();  
    363.                 }  
    364.             }  
    365.         }  
    366.   
    367.     }  
    368.   
    369.   
    370.   
    371.     public void onPreviewFrame(byte[] data, Camera camera) {  
    372.         // TODO Auto-generated method stub  
    373.   
    374.     }  
    375. }  

    需要注意的有以下几点:

    1,为了让程序适用不同的手机,onCreate函数里用如下代码初始化SurfaceView的大小,避免以前写死的方法:

     public void initView(){
      mPreviewSV = (SurfaceView)findViewById(R.id.previewSV);
      WindowManager wm = (WindowManager)getSystemService(Context.WINDOW_SERVICE);
      Display display = wm.getDefaultDisplay();
            LayoutParams lpSV = mPreviewSV.getLayoutParams();
            lpSV.width = display.getWidth();
            lpSV.height = (int) ((float)display.getHeight()*0.75);
            mPreviewSV.setLayoutParams(lpSV);

       mPhotoImgBtn = (ImageButton)findViewById(R.id.photoImgBtn);
      LayoutParams lp = mPhotoImgBtn.getLayoutParams();
      lp.width = 240;
      lp.height = 240;  
      mPhotoImgBtn.setLayoutParams(lp);    
      mPhotoImgBtn.setOnClickListener(new PhotoOnClickListener());
      mPhotoImgBtn.setOnTouchListener(new MyOnTouchListener());
     }

    2,关于ZoomBar的代码片段很简短,如下:


       mPhotoImgBtn = (ImageButton)findViewById(R.id.photoImgBtn);
      LayoutParams lp = mPhotoImgBtn.getLayoutParams();
      lp.width = 240;
      lp.height = 240;  
      mPhotoImgBtn.setLayoutParams(lp);    
      mPhotoImgBtn.setOnClickListener(new PhotoOnClickListener());
      mPhotoImgBtn.setOnTouchListener(new MyOnTouchListener());
     }
      //添加ZoomBar
      mZoomBar = (SeekBar)findViewById(R.id.seekbar_zoom);
      mZoomBar.setOnSeekBarChangeListener(new OnSeekBarChangeListener() {
       
       public void onStopTrackingTouch(SeekBar seekBar) {
        // TODO Auto-generated method stub
        
       }
       
       public void onStartTrackingTouch(SeekBar seekBar) {
        // TODO Auto-generated method stub
        
       }
       
       public void onProgressChanged(SeekBar seekBar, int progress,
         boolean fromUser) {
        // TODO Auto-generated method stub
        Parameters p = myCamera.getParameters();
        p.setZoom(progress);
        myCamera.setParameters(p);
       }
      });

    3,在initCamera函数里,查询camera支持的聚焦模式,如果带连续视频聚焦则使用连续视频聚焦,否则使用自动聚焦:


       mPhotoImgBtn = (ImageButton)findViewById(R.id.photoImgBtn);
      LayoutParams lp = mPhotoImgBtn.getLayoutParams();
      lp.width = 240;
      lp.height = 240;  
      mPhotoImgBtn.setLayoutParams(lp);    
      mPhotoImgBtn.setOnClickListener(new PhotoOnClickListener());
      mPhotoImgBtn.setOnTouchListener(new MyOnTouchListener());
     }
    List<String> focuseMode = (myParam.getSupportedFocusModes());
       for(int i=0; i<focuseMode.size(); i++){
        Log.i(tag, focuseMode.get(i));
        if(focuseMode.get(i).contains("continuous")){
         myParam.setFocusMode(Camera.Parameters.FOCUS_MODE_CONTINUOUS_VIDEO);
        }
        else{
         myParam.setFocusMode(Camera.Parameters.FOCUS_MODE_AUTO);
        }
       }

    4,同样在initCamera函数里,设置ZoomBar的最大值:
    //设置mZoomBar的最大值
       mZoomBar.setMax(myParam.getMaxZoom());

    后续将写专文分析Camera4.0的源码,并且模仿到自己的代码中!

  • 相关阅读:
    php date函数
    jquery AJAX教程
    Magento 批量修改订单状态为 Completed
    php 复习笔记 乱
    正则替换 php js
    magento订单状态修改
    换个心态继续走IT路
    神奇的HTML5,效果超炫,用Google chrome浏览
    PHP $_SERVER参数
    第六章 线程基础
  • 原文地址:https://www.cnblogs.com/android100/p/Android-Camera.html
Copyright © 2020-2023  润新知