android camera(4)

先说说我的测试机器:nexus s。以下的结果都是通过nexus s上测试通过。


这次先说说步骤:下载zxing2.0,里面的core有个core.jar这个有用,将它引用到你的工程下。接着在目录android\src\com\google\zxing\client\android\PlanarYUVLuminanceSource.java,将它复制到你的工程的src文件夹下,记得改了它的包名。准备工作就完成了。然后就上代码:

package com.TestCamera2;
import com.google.zxing.BinaryBitmap;   
import com.google.zxing.MultiFormatReader;   
import com.google.zxing.Result;   
import com.TestCamera2.PlanarYUVLuminanceSource;   
import com.google.zxing.common.HybridBinarizer;   
import java.io.BufferedOutputStream;
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.util.Timer;
import java.util.TimerTask;
import android.app.Activity;
import android.content.Context;
import android.content.pm.ActivityInfo;
import android.graphics.Bitmap;
import android.graphics.Bitmap.CompressFormat;
import android.graphics.BitmapFactory;
import android.graphics.Canvas;
import android.graphics.ImageFormat;
import android.graphics.PixelFormat;
import android.graphics.Rect;
import android.graphics.YuvImage;
import android.hardware.Camera;
import android.hardware.Camera.PictureCallback;
import android.hardware.Camera.ShutterCallback;
import android.os.Bundle;
import android.os.Environment;
import android.util.Log;
import android.view.Display;
import android.view.KeyEvent;
import android.view.SurfaceHolder;
import android.view.View;
import android.view.SurfaceHolder.Callback;
import android.view.View.OnClickListener;
import android.view.SurfaceView;
import android.view.Window;
import android.view.WindowManager;
import android.widget.Button;
import android.widget.ImageView;
import android.widget.TextView;
import android.widget.Toast;
public class TestCamera2Activity extends Activity {
    private Camera camera;
    private SurfaceView surfaceView;
    private boolean preview;
    final static int width = 352;   
    final static int height = 288;   
    int dstLeft, dstTop, dstWidth, dstHeight;   
    private Timer mTimer;
    private MyTimerTask mTimerTask ;
    private Button btn;
    private Camera.PreviewCallback previewCallback;
   
    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        
        requestWindowFeature(Window.FEATURE_NO_TITLE);
        setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE);
        Window window = getWindow();
        window.setFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN, WindowManager.LayoutParams.FLAG_FULLSCREEN);
        window.addFlags(WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON);
        setContentView(R.layout.main);
        surfaceView =  (SurfaceView) findViewById(R.id.preview_view);
        surfaceView.getHolder().setType(SurfaceHolder.SURFACE_TYPE_PUSH_BUFFERS);
        surfaceView.getHolder().setFixedSize(352, 288); //设定surface的大小,必须要,除非你的surface刚好是你手机preview允许的大小              
       surfaceView.getHolder().addCallback(new SurfaceViewCallback());
       btn=(Button)findViewById(R.id.button1);
       btn.setOnClickListener(new OnClickListener(){
		public void onClick(View v) {
			mTimer = new Timer(); 
		       mTimerTask = new MyTimerTask(); 
		       mTimer.schedule(mTimerTask, 0, 80);
			
		}
       });
       previewCallback = new Camera.PreviewCallback() {
    	     public void onPreviewFrame(byte[] data, Camera arg1) {
    	    	 if(data!=null){
    	    		 Log.i("data", "ok");
    	    		if (dstLeft == 0) {// 只赋值一次 
		                dstLeft = surfaceView.getLeft() * width 
		                        / getWindowManager().getDefaultDisplay().getWidth(); 
		                dstTop = surfaceView.getTop() * height 
		                        / getWindowManager().getDefaultDisplay().getHeight(); 
		                dstWidth = (surfaceView.getRight() - surfaceView.getLeft()) 
		                        * width 
		                        / getWindowManager().getDefaultDisplay().getWidth(); 
		                dstHeight = (surfaceView.getBottom() - surfaceView.getTop()) 
		                        * height 
		                        / getWindowManager().getDefaultDisplay().getHeight(); 
		            } 
					//
					
			PlanarYUVLuminanceSource source = new PlanarYUVLuminanceSource(data, width, height, dstLeft, dstTop, dstWidth, dstHeight,false); 
		            // 取得灰度图 
		            Bitmap bm = source.renderCroppedGreyscaleBitmap(); 
		            // 保存灰度图 
		            String picDirStr = Environment.getExternalStorageDirectory()+"/"; 
		            File picDir = new File(picDirStr); 
		            if(!picDir.exists()){ 
		                picDir.mkdir(); 
		            } 
		            String picName = picDirStr + System.currentTimeMillis() + ".jpg"; 
		            File myCaptureFile = new File(picName); 
		            try { 
		                BufferedOutputStream bos = new BufferedOutputStream( new FileOutputStream(myCaptureFile)); 
		                bm.compress(Bitmap.CompressFormat.JPEG, 80, bos); 
		                bos.flush(); 
		                bos.close(); 
		                camera.startPreview(); 
		                Log.i("pic","ok");
		            } catch (Exception e) { 
		                e.printStackTrace();
		            }
		            //		            
		            BinaryBitmap bitmap = new BinaryBitmap(new HybridBinarizer(source)); 
		            MultiFormatReader reader = new MultiFormatReader(); 
		            try { 
		                Result result = reader.decode(bitmap); 
		                String strResult = "BarcodeFormat:"
		                        + result.getBarcodeFormat().toString() + "  text:"
		                        + result.getText(); 
		                Log.i("result",strResult);
		                Toast.makeText(getApplicationContext(), strResult, Toast.LENGTH_LONG+2000).show();
		            	mTimer.cancel();		
		            } catch (Exception e) { 
		            	 Log.i("result","faile");
		            } 
				}
    	    	 else{
        	    	 Log.i("data", "null");
        	     }
    	     }   	        	       
       };
    }

    private final class SurfaceViewCallback implements SurfaceHolder.Callback {
        public void surfaceCreated(SurfaceHolder holder) {
        	camera = Camera.open();      
        }
    
        public void surfaceChanged(SurfaceHolder holder, int format, int width,
                int height) {
        	Camera.Parameters parameters = camera.getParameters();
        	parameters.setPreviewSize(width, height);       	
			parameters.setPreviewFrameRate(5);		
			parameters.setPictureFormat(PixelFormat.JPEG);		
			parameters.set("jpeg-quality", 85);
        	camera.setParameters(parameters);        	       	
            try{           	
            	camera.setPreviewDisplay(holder);
            	preview = true;
            	Log.i("camera", "camera open!");
            }catch(IOException exception) { 
                camera.release(); 
                camera = null; 
            } 
        	camera.startPreview();
        	Log.i("camera","camera preview");
        }
        public void surfaceDestroyed(SurfaceHolder holder) {
        	if (camera != null) { 
        		 if(preview) {
                     camera.stopPreview();
                     preview = false;
                     Log.i("destroyprevie", "ok!");
                 }       
                 camera.release();
                 camera = null;
             }
            } 
        }

    class MyTimerTask extends TimerTask {   
        @Override  
        public void run() {   
           camera.autoFocus(new Camera.AutoFocusCallback() {
				public void onAutoFocus(boolean success, Camera camera) {
					if(success){
						Log.i("focus","ok!");
						camera.setOneShotPreviewCallback(previewCallback);
					}
				}
			});       
        }
    }
}

接着解说一下这个过程:你按button,手机就开始自动对焦(由Timer不断触发),当对焦成功时,调用函数onPreviewFrame来取得那一帧的图片data然后生成对象PlanarYUVLuminanceSource,由这个对象返回一张灰度图,我将它保存下来以便观察。接下来的工作就是交给解码器完成工作了,若解码成功则直接输出解码结果,然后。如果解码不成功,会不断对焦,不断进行尝试。大家可能觉得这个过程十分简单,但是对于这只菜鸟要用一个星期的时间,花时间搞懂照相机,花时间上网找资料,表示看了很多资料http://www.cnblogs.com/liuan/category/347622.html(我从这个博客学到很多,要感谢一下这个博客的博主),花时间看看zxing,然后慢慢学习。这个过程也学习到很多东西。


最后我说说我这个demo的问题。首先看看我的布局文件

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:orientation="horizontal"
    android:layout_width="fill_parent"
    android:layout_height="fill_parent"
    >
  <RelativeLayout
  android:layout_width="fill_parent"
  android:layout_height="wrap_content"
 android:layout_weight="1" >
<SurfaceView android:id="@+id/preview_view"
 android:layout_width="fill_parent"
 android:layout_height="fill_parent"
android:screenOrientation="landscape" />
</RelativeLayout>
<Button android:text="Button" android:id="@+id/button1" android:layout_width="wrap_content" android:layout_height="wrap_content"></Button>
</LinearLayout>
这样的布局导致不能知道surfaceview的大小,但是surfaceview比较大,所以必须要设定 surfaceView.getHolder().setFixedSize(352, 288);我还操蛋的发现parameters.setPreviewSize(width, height); 根本不起作用的,所以还是不设定好,直接设定surfaceview。然后我将surfaceview设定成352*288,这个surfaceview就太小了而且所得到的灰度图大概只能surfaceview的一半大,所以解码永远不成功的,于是我去看了类 PlanarYUVLuminanceSource的构造函数,但是不知所云。我猜想,因为源程序是满屏幕只取中间那个很小的view的灰度图,所以我的小surfaceview被活生生的截图了(本来就刚刚好找到条形码),所以解码不成功。更多发现留给大家了。所以我直接将surfaceview放得大大好了。


接下来我的android camera系列就结束了(我留给自己的工作是实现跟源程序一样的界面)。这次让我感慨良多。这个是我第一次写这样的文章,发觉是超级难写。因为你要尽量保证你的准确性还要描述清楚(我知道我的表达能力十分有限),那么就不得不做大量的尝试,查看大量的资料(我花了一个多星期吧,才开始接触android两个星期左右)。


附上demo:android camera(4)



警告:android camera系列的文章是由一个刚接触android不到一个月的菜鸟所写,所以必然存在很多错误,请大家指出




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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值