android入门:zxing学习笔记(四)
2016-07-14 16:26
429 查看
Camera取景后显示于屏幕上,是个挺简单的过程,但这会出现各种意料不到的问题,例如之前说的屏幕横竖屏与预览图片之间的方向,图片拉伸,还有在Barcode Scanner中,简单的旋转了图片预览方向后,会出现特征点标记错位,等等。
第三篇简单的完成了相机的取景,还没有将取景的图片拍照存储下来。若想实现拍照的效果,则需要实现回调函数:Camera.PreviewCallback接口。接上一篇的代码,在此实现拍照的功能,将图片显示出来。之前一直在看Barcode Scanner的源码,并只是在其代码上修剪。当昨天自己来实现Camera的自动聚焦时,并遇到比较纠结的问题。在不出意外的情况下,Camera的使用还是挺简单的。
先在此贴出代码,最简单,代码经过了测试,正常运行,测试机是HTC MyTouch 3G slide。
需要的权限:
整个代码:
与上一篇的简单预览相比,这篇增加了两个内容,一个是自动聚焦,一个是拍照。代码看上去很简单,没多少内容。但不亲自测试下,还会发现不少。
刚开始在Samsung S5570 galaxy mini上测试,总是不能成功的拍照。调试跟踪后,发现自动聚焦总是失败,聚焦失败就没有进行拍照操作。后面并尝试将自动聚焦代码注释掉,直接拍照,发现也是无法显示拍照的结果。之前的PreviewCallback的代码如下:
这行代码返回的总是null,即bitmap没有成功生成。对这些代码本来就是拿来用,功能实现了,就行,对这些都只是简单的了解,当遇到bug后并百思不得其解。后来在网上几经查找发现原来是BitmapFactory.decodeByteArray只支持一定的格式,camara支持的previewformat格式为NV21,所以在获得bitmap时,需要进行转换。通过YuvImage类来转换成JPEG格式,再显示出来。具体讨论,请点这里。
解决照片的显示问题后,还有一个问题便是自动聚焦失败。上面特意强调了使用的事HTC 的手机测试成功,是因为之前在samsung s5570 上测试总是失败,拿到HTC的那款手机上立马成功。应该是三星的这款手机不支持自动聚焦。之前在这个三星手机上跑过Barcode Scanner,就自以为这手机能够自动聚焦,并一直在查找自己代码的原因。后面在仔细的读了Barcode Scanner的代码后,发现他得处理方式是:
首先实现拍照,再是实现聚焦,并且重载的聚焦回调函数是隔一段时间再次发出聚焦的请求,实现不断的聚焦。
聚焦于拍照之前没有先后的逻辑关系,聚焦为了拍照更清晰。这样,关于camera取景聚焦拍照的简单过程并如上了。
还有一个关键的点幷是回调函数。以前没有接触java代码,在看到很多接口监听处理的代码时,总是很困惑。譬如一段简单的button:
如上的代码实现了点击监听,通过回调函数,当有点击操作时,并执行onClick函数。这就是一个简单的回调函数的使用。
第三篇简单的完成了相机的取景,还没有将取景的图片拍照存储下来。若想实现拍照的效果,则需要实现回调函数:Camera.PreviewCallback接口。接上一篇的代码,在此实现拍照的功能,将图片显示出来。之前一直在看Barcode Scanner的源码,并只是在其代码上修剪。当昨天自己来实现Camera的自动聚焦时,并遇到比较纠结的问题。在不出意外的情况下,Camera的使用还是挺简单的。
先在此贴出代码,最简单,代码经过了测试,正常运行,测试机是HTC MyTouch 3G slide。
需要的权限:
1 <uses-permission android:name="android.permission.CAMERA" /> 2 <uses-feature android:name="android.hardware.camera" /> 3 <uses-feature android:name="android.hardware.camera.autofocus" />
整个代码:
1 import java.io.ByteArrayOutputStream; 2 import java.io.IOException; 3 import java.util.Timer; 4 import java.util.TimerTask; 5 6 import android.app.Activity; 7 import android.content.Context; 8 import android.graphics.Bitmap; 9 import android.graphics.BitmapFactory; 10 import android.graphics.ImageFormat; 11 import android.graphics.Rect; 12 import android.graphics.YuvImage; 13 import android.hardware.Camera; 14 import android.os.Bundle; 15 import android.util.Log; 16 import android.view.Display; 17 import android.view.SurfaceHolder; 18 import android.view.SurfaceView; 19 import android.view.WindowManager; 20 import android.widget.ImageView; 21 22 public class CameraTestActivity extends Activity implements SurfaceHolder.Callback { 23 private static String TAG = CameraTestActivity.class.getSimpleName(); 24 private SurfaceHolder surfaceHolder; 25 private Camera camera; 26 private ImageView imageView; 27 private Timer mTimer; 28 private TimerTask mTimerTask; 29 30 private Camera.AutoFocusCallback mAutoFocusCallBack; 31 private Camera.PreviewCallback previewCallback; 32 33 /** Called when the activity is first created. */ 34 @Override 35 public void onCreate(Bundle savedInstanceState) { 36 super.onCreate(savedInstanceState); 37 setContentView(R.layout.main); 38 SurfaceView surfaceView = (SurfaceView) findViewById(R.id.preview_view); 39 imageView = (ImageView) findViewById(R.id.image_view); 40 surfaceHolder = surfaceView.getHolder(); 41 surfaceHolder.addCallback(this); 42 surfaceHolder.setType(SurfaceHolder.SURFACE_TYPE_PUSH_BUFFERS); 43 mAutoFocusCallBack = new Camera.AutoFocusCallback() { 44 @Override 45 public void onAutoFocus(boolean success, Camera camera) { 46 if (success) { 47 // isAutoFocus = true; 48 camera.setOneShotPreviewCallback(previewCallback); 49 Log.d(TAG, "onAutoFocus success"); 50 } 51 } 52 }; 53 54 previewCallback = new Camera.PreviewCallback() { 55 @Override 56 public void onPreviewFrame(byte[] data, Camera arg1) { 57 if (data != null) 58 { 59 Camera.Parameters parameters = camera.getParameters(); 60 int imageFormat = parameters.getPreviewFormat(); 61 Log.i("map", "Image Format: " + imageFormat); 62 63 Log.i("CameraPreviewCallback", "data length:" + data.length); 64 if (imageFormat == ImageFormat.NV21) 65 { 66 // get full picture 67 Bitmap image = null; 68 int w = parameters.getPreviewSize().width; 69 int h = parameters.getPreviewSize().height; 70 71 Rect rect = new Rect(0, 0, w, h); 72 YuvImage img = new YuvImage(data, ImageFormat.NV21, w, h, null); 73 ByteArrayOutputStream baos = new ByteArrayOutputStream(); 74 if (img.compressToJpeg(rect, 100, baos)) 75 { 76 image = BitmapFactory.decodeByteArray(baos.toByteArray(), 0, baos.size()); 77 imageView.setImageBitmap(image); 78 } 79 80 } 81 } 82 } 83 }; 84 85 mTimer = new Timer(); 86 mTimerTask = new CameraTimerTask(); 87 mTimer.schedule(mTimerTask, 0, 500); 88 } 89 90 @Override 91 public void surfaceChanged(SurfaceHolder arg0, int arg1, int arg2, int arg3) { 92 // TODO Auto-generated method stub 93 } 94 95 @Override 96 public void surfaceCreated(SurfaceHolder arg0) { 97 // TODO Auto-generated method stub 98 initCamera(); 99 } 100 101 @Override 102 public void surfaceDestroyed(SurfaceHolder arg0) { 103 // TODO Auto-generated method stub 104 if (camera != null) { 105 camera.stopPreview(); 106 camera.release(); 107 camera = null; 108 } 109 previewCallback = null; 110 mAutoFocusCallBack = null; 111 } 112 113 public void initCamera() { 114 camera = Camera.open(); 115 Camera.Parameters parameters = camera.getParameters(); 116 WindowManager wm = (WindowManager) getSystemService(Context.WINDOW_SERVICE); // 获取当前屏幕管理器对象 117 Display display = wm.getDefaultDisplay(); // 获取屏幕信息的描述类 118 parameters.setPreviewSize(display.getWidth(), display.getHeight()); 119 camera.setParameters(parameters); 120 try { 121 camera.setPreviewDisplay(surfaceHolder); 122 } catch (IOException e) { 123 System.out.println(e.getMessage()); 124 } 125 camera.startPreview(); 126 } 127 128 class CameraTimerTask extends TimerTask { 129 @Override 130 public void run() { 131 if (camera != null) { 132 camera.autoFocus(mAutoFocusCallBack); 133 } 134 } 135 } 136 }
与上一篇的简单预览相比,这篇增加了两个内容,一个是自动聚焦,一个是拍照。代码看上去很简单,没多少内容。但不亲自测试下,还会发现不少。
刚开始在Samsung S5570 galaxy mini上测试,总是不能成功的拍照。调试跟踪后,发现自动聚焦总是失败,聚焦失败就没有进行拍照操作。后面并尝试将自动聚焦代码注释掉,直接拍照,发现也是无法显示拍照的结果。之前的PreviewCallback的代码如下:
1 Bitmap bitmap = BitmapFactory.decodeByteArray(data, 0, data.length);
这行代码返回的总是null,即bitmap没有成功生成。对这些代码本来就是拿来用,功能实现了,就行,对这些都只是简单的了解,当遇到bug后并百思不得其解。后来在网上几经查找发现原来是BitmapFactory.decodeByteArray只支持一定的格式,camara支持的previewformat格式为NV21,所以在获得bitmap时,需要进行转换。通过YuvImage类来转换成JPEG格式,再显示出来。具体讨论,请点这里。
解决照片的显示问题后,还有一个问题便是自动聚焦失败。上面特意强调了使用的事HTC 的手机测试成功,是因为之前在samsung s5570 上测试总是失败,拿到HTC的那款手机上立马成功。应该是三星的这款手机不支持自动聚焦。之前在这个三星手机上跑过Barcode Scanner,就自以为这手机能够自动聚焦,并一直在查找自己代码的原因。后面在仔细的读了Barcode Scanner的代码后,发现他得处理方式是:
1 CameraManager.get().requestPreviewFrame(decodeThread.getHandler(), R.id.decode);//实现拍照 2 CameraManager.get().requestAutoFocus(this, R.id.auto_focus);//实现聚焦
首先实现拍照,再是实现聚焦,并且重载的聚焦回调函数是隔一段时间再次发出聚焦的请求,实现不断的聚焦。
1 public void onAutoFocus(boolean success, Camera camera) { 2 if (autoFocusHandler != null) { 3 Message message = autoFocusHandler.obtainMessage(autoFocusMessage, success); 4 // Simulate continuous autofocus by sending a focus request every 5 // AUTOFOCUS_INTERVAL_MS milliseconds. 6 //Log.d(TAG, "Got auto-focus callback; requesting another"); 7 autoFocusHandler.sendMessageDelayed(message, AUTOFOCUS_INTERVAL_MS); 8 autoFocusHandler = null; 9 } else { 10 Log.d(TAG, "Got auto-focus callback, but no handler for it"); 11 } 12 }
聚焦于拍照之前没有先后的逻辑关系,聚焦为了拍照更清晰。这样,关于camera取景聚焦拍照的简单过程并如上了。
还有一个关键的点幷是回调函数。以前没有接触java代码,在看到很多接口监听处理的代码时,总是很困惑。譬如一段简单的button:
1 private final Button.OnClickListener addCardListener = new TextView.OnClickListener() { 2 @Override 3 public void onClick(View v) { 4 //在此实现button点击后的操作 5 } 6 };
如上的代码实现了点击监听,通过回调函数,当有点击操作时,并执行onClick函数。这就是一个简单的回调函数的使用。
相关文章推荐
- java Android 都可以使用的万能关闭流工具类
- 屏幕密度和图片资源路径的对应关系
- 新Android工程src和layout目录为空
- android中wifi原理及流程分析(很经典)
- 【Android】Android之开发问题集
- Android自定义控件下拉刷新
- Android 5.1系统禁止通知状态栏下拉
- RecyclerView中的多种布局
- Android软件下载及环境配置(SDK无需代理翻墙,离线更新)
- Android获取屏幕分辨率及DisplayMetrics简介
- Android缓存机制&一个缓存框架推荐
- AndroidAnnotations介绍
- Android热修复
- Android 动画
- AndroidAnnotations使用详解
- LinkedList基本用法
- Android调用系统的打电话和发短信功能
- Android Studio官方文档之添加多种密度的矢量图形
- [转]关于Android系统的”点九”
- Android虚拟机内存管理垃圾回收【转】