200字范文,内容丰富有趣,生活中的好帮手!
200字范文 > android 使用 surfaceView 获取 camera 预览界面图像数据

android 使用 surfaceView 获取 camera 预览界面图像数据

时间:2019-02-10 09:35:47

相关推荐

android 使用 surfaceView 获取 camera 预览界面图像数据

android中,通过相机获取预览界面的需求似乎很变态,好像也没有什么使用场景。但是,有一个场景需要获取预览界面的图像,就是扫码,比如微信,支付宝的扫一扫,就是需要获取预览界面的图像数据的。

实现逻辑比较简单,不过肯定比打开系统相机要麻烦一点的。

下面简单说一下实现步骤:

实例化一个SurfaceView。在surfaceCreated()回调中去实例化Camera对象,去自动对焦。在onAutoFocus()回调中去调用camera.takePicture(null,null,callback);。在第3步的callback里面去获取预览图像数据int data[]。(可选)将获取的数据换成成文件。(可选)将该文件对象加载成bitmap对象。在不使用的使用释放相机资源。

代码细节:

清单文件:

<uses-feature android:name="android.hardware.camera" /><uses-feature android:name="android.hardware.camera.autofocus" /><uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" /><uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" /><uses-permission android:name="android.permission.CAMERA" /><uses-permission android:name="android.permission.RECORD_AUDIO" />

java代码:

package com.python.cat.testgradle;import android.Manifest;import android.app.Activity;import android.content.Context;import android.graphics.Bitmap;import android.graphics.BitmapFactory;import android.hardware.Camera;import android.os.Bundle;import android.view.SurfaceHolder;import android.view.SurfaceView;import android.view.View;import android.widget.Button;import android.widget.FrameLayout;import android.widget.Toast;import com.apkfuns.logutils.LogUtils;import com.google.zxing.BinaryBitmap;import com.google.zxing.ChecksumException;import com.google.zxing.FormatException;import com.google.zxing.NotFoundException;import com.google.zxing.RGBLuminanceSource;import com.google.zxing.Result;import com.mon.GlobalHistogramBinarizer;import com.google.zxing.qrcode.QRCodeReader;import com.yanzhenjie.permission.Action;import com.yanzhenjie.permission.AndPermission;import java.io.File;import java.io.FileOutputStream;import java.io.IOException;import java.util.Arrays;import java.util.List;public class UseCameraActivity extends Activity {private Activity get() {return this;}@Overrideprotected void onCreate(Bundle savedInstanceState) {super.onCreate(savedInstanceState);setContentView(R.layout.activity_asome);setTitle(getClass().getSimpleName());final FrameLayout frameLayout = findViewById(R.id.prev_content_layout);Button btn = findViewById(R.id.start_camera_preview);btn.setOnClickListener(new View.OnClickListener() {@Overridepublic void onClick(View v) {AndPermission.with(get()).permission(Manifest.permission.CAMERA,Manifest.permission.WRITE_EXTERNAL_STORAGE).onDenied(new Action() {@Overridepublic void onAction(List<String> permissions) {LogUtils.e("error....." + permissions);}}).onGranted(new Action() {@Overridepublic void onAction(List<String> permissions) {LogUtils.w("you can do..");ScanView scanView = new ScanView(get());frameLayout.removeAllViews();frameLayout.addView(scanView);}}).start();}});}static class ScanView extends SurfaceView implements SurfaceHolder.Callback,Camera.AutoFocusCallback {private Camera mCamera;private final File fileImg;private ScanView self;public ScanView(Context context) {super(context);fileImg = new File(context.getCacheDir(), "prev_view.jpg");SurfaceHolder mHolder = getHolder();self = this;mHolder.addCallback(this);// deprecated setting, but required on Android versions prior to 3.0mHolder.setType(SurfaceHolder.SURFACE_TYPE_PUSH_BUFFERS);}@Overridepublic void onAutoFocus(boolean success, Camera camera) {LogUtils.w("auto focus..." + success);if (mCamera != null) {mCamera.takePicture(null, null, null, new Camera.PictureCallback() {@Overridepublic void onPictureTaken(byte[] data, Camera camera) {mCamera.cancelAutoFocus();mCamera.stopPreview(); // 拿到数据就停止!!!LogUtils.w("========data========");LogUtils.w("----------data-----------------");// camera.startPreview();File pictureFile = fileImg;if (pictureFile == null) {LogUtils.e("Error creating media file, check storage permissions: " +null);return;}if (data == null) {return;}try {LogUtils.d(data);FileOutputStream fos = new FileOutputStream(pictureFile);fos.write(data);fos.close();LogUtils.e("save preview complete###!!!");LogUtils.e("save preview complete###!!!" + pictureFile);BitmapFactory.Options options = new BitmapFactory.Options();options.inJustDecodeBounds = true;BitmapFactory.decodeFile(pictureFile.getAbsolutePath(), options);options.inJustDecodeBounds = false;int outWidth = options.outWidth;int outHeight = options.outHeight;if (outWidth >= getWidth() * 2) {options.inSampleSize = outWidth / getWidth();}if (outHeight >= getHeight() * 2) {options.inSampleSize = outHeight / getHeight();}Bitmap bmp = BitmapFactory.decodeFile(pictureFile.getAbsolutePath(), options);Result result = parseInfoFromBitmap(bmp);if (result != null) {Toast.makeText(getContext(), "INFO:" + result.getText(), Toast.LENGTH_SHORT).show();LogUtils.w("解析成功:" + result);} else {LogUtils.e("再次尝试中....");mCamera.startPreview();mCamera.autoFocus(self);// todo:这里也可以做最大重试次数的限制...}} catch (Exception e) {LogUtils.e("Error accessing file: " + e.getMessage());}}});}}public Result parseInfoFromBitmap(Bitmap bitmap) {int[] pixels = new int[bitmap.getWidth() * bitmap.getHeight()];bitmap.getPixels(pixels, 0, bitmap.getWidth(), 0, 0, bitmap.getWidth(), bitmap.getHeight());LogUtils.w("### pixels dest==" + Arrays.toString(pixels));RGBLuminanceSource source = new RGBLuminanceSource(bitmap.getWidth(),bitmap.getHeight(), pixels);GlobalHistogramBinarizer binarizer = new GlobalHistogramBinarizer(source);BinaryBitmap image = new BinaryBitmap(binarizer);Result result = null;try {result = new QRCodeReader().decode(image);return result;} catch (NotFoundException e) {e.printStackTrace();Toast.makeText(getContext(), "非二维码图片,不能解析", Toast.LENGTH_SHORT).show();} catch (ChecksumException e) {e.printStackTrace();} catch (FormatException e) {e.printStackTrace();}return null;}@Overridepublic void surfaceCreated(SurfaceHolder holder) {LogUtils.e("x surfaceCreated.. #####");try {mCamera = Camera.open();mCamera.setPreviewDisplay(holder);mCamera.setDisplayOrientation(90);Camera.Parameters parameters = mCamera.getParameters();//parameters.setPictureSize(1600, 1200);//parameters.setPreviewSize(640, 480);mCamera.setParameters(parameters);mCamera.startPreview();mCamera.autoFocus(this);LogUtils.e("surfaceCreated.. #####");} catch (IOException e) {LogUtils.e("Error setting camera preview: " + e.getMessage());}}@Overridepublic void surfaceChanged(SurfaceHolder holder, int format, int width, int height) {LogUtils.w("--change-");}@Overridepublic void surfaceDestroyed(SurfaceHolder holder) {LogUtils.w("destroy--");if (mCamera != null) {mCamera.cancelAutoFocus();mCamera.stopPreview();mCamera.release();}}}}

布局文件:

<RelativeLayout xmlns:android="/apk/res/android"xmlns:app="/apk/res-auto"xmlns:tools="/tools"android:layout_width="match_parent"android:layout_height="match_parent"tools:context=".UseCameraActivity"><Button android:id="@+id/start_camera_preview"android:layout_width="wrap_content"android:layout_height="wrap_content"android:layout_alignParentBottom="true"android:text="@string/start_camera_preview" /><FrameLayout android:id="@+id/prev_content_layout"android:layout_width="match_parent"android:layout_height="match_parent"android:layout_above="@id/start_camera_preview"></FrameLayout></RelativeLayout>

gradle配置(可选):

implementation 'com.yanzhenjie:permission:2.0.0-rc4' // 运行时权限语法糖implementation 'com.google.zxing:core:3.3.1' // zxing 解析二维码图片

嗯,以上就是获取相机预览图像数据的代码了。不过,这里用的Camera接口是过时的了,不建议使用。不过可以运行。我目前的compileSdkVersion=26

就酱咯。 完整app代码也许有的吧。

=======

update: 关于Camera2,我选择放弃….

官方的说法是:

The android.hardware.camera2 package provides an interface to individual camera devices connected to an Android device. It replaces the deprecated Camera class.

This package models a camera device as a pipeline, which takes in input requests for capturing a single frame, captures the single image per the request, and then outputs one capture result metadata packet, plus a set of output image buffers for the request. The requests are processed in-order, and multiple requests can be in flight at once. Since the camera device is a pipeline with multiple stages, having multiple requests in flight is required to maintain full framerate on most Android devices.

反正是看懂了一句话,就是用来替代Camera的。

但是,真的很麻烦。我没有找到中文的,可以直接运行的案例,找到了两个外国人写的博客,里面给了完整的代码。不过估计不能直接访问。我把拷贝到我的项目里面去了。可以直接运行

完整app代码

因为每一篇代码都很长,我就不贴出来了,说一下路径。

com.python.cat.testgradle.MainActivity.java[由于这个原始代码没有加动态权限申请,我手动添加了一下…]

com.python.cat.testgradle.AndroidCameraApi.java

我给的是我代码的路径,以及原始链接。

不清楚是出于什么考虑,camera2里面比camera多了好几类,复杂度也提升了不少。有需要的可以研究一下。上手难度大于camera。(目前我还是一头雾水,对于camera2)。

中文的找到一个:这个我并没有去下载运行验证,不过看博客里面写的挺多的。

本内容不代表本网观点和政治立场,如有侵犯你的权益请联系我们处理。
网友评论
网友评论仅供其表达个人看法,并不表明网站立场。