安卓开发——相机:拍照并处理图片
来源:互联网 发布:哔哩哔哩 for mac 编辑:程序博客网 时间:2024/05/17 06:15
本次使用的是Camera API来实现的,并不是使用隐式Intent与照相机进行交互的。所以我们使用SurfaceView类和相机硬件来实现实时展示拍照界面,以及拍照后的图片处理。
相机是一种独占性资源:也就是说一次只能有一个activity可以调用相机。因此,我们在使用相机硬件资源时需要时刻注意,使用完资源后要释放资源!!!
SurfaceView实例可以用来充当相机的取景器。SurfaceView是一种特殊的视图,可直接将想要显示的内容渲染输出到设备上(也可以用来播放视频)。
拍照
获取权限
要使用相机,首先我们就要获取相关的权限:(AndroidMenifest.xml)
<uses-permission android:name="android.permission.CAMERA"/> <uses-permission android:name="android.permission.FLASHLIGHT"/> <uses-feature android:name="android.hardware.Camera"/><uses-feature android:name="android.hardware.camera.autofocus" />
PS:屏幕显示方向可以在activity中的android:screenOrientation标签定义:
1. landscape : 横屏
2. portrait : 竖屏
<activity android:name=".CameraActivity" android:screenOrientation="landscape"></activity>
Camera API
这里使用的是android.hardware.Camera包中的Camera类来打开相机的。
其中Camera操作主要包括以下三个方法:
1. public static Camera open(int);
2. public static Camera open();
3. public final void release();
open()可以打开一个Camera资源,含参数的open方法则是在API9以后加入的(推荐使用这个)。release()方法则用于释放获取的相机资源。一般情况下只有当activity视图为在前台可见时才需要使用相机,所以我们考虑在onResume()方法中申请使用相机,而当视图离开前台时,即在onPause()方法中释放获取的相机资源。
@Override public void onResume() { super.onResume(); if(Build.VERSION.SDK_INT >= Build.VERSION_CODES.GINGERBREAD) mCamera = Camera.open(0); else mCamera = Camera.open(); } @Override public void onPause() { super.onPause(); if(mCamera != null){ mCamera.release(); mCamera = null; } }
SurfaceView实现取景器
SurfaceView:是我们用来显示图像的视图组件。
Surface:可以看成是原始像素数据的缓冲区。
SurfaceHolder:是和Surface对象连接的重要纽带。(可以理解为通过SurfaceHolder给Surface对象设置像素数据)。
Surface对象是有生命周期的,即当SurfaceView在前台显示时会生成Surface对象,当SurfaceView消失时,Surface对象也会被销毁。因为当Surface不存在时我们需要保证Surface中没有需要绘制的对象。所以我们可以在Surface创建后把相机连接到SurfaceHolder上,当Surface被销毁后,我们把SurfaceHolder和相机的连接取消。为了实现这个我们需要使用SurfaceView.Callback接口中的三个方法。
mSurfaceView = (SurfaceView) v.findViewById(R.id.camera_surfaceView); SurfaceHolder holder = mSurfaceView.getHolder(); //holder.setType(SurfaceHolder.SURFACE_TYPE_PUSH_BUFFERS); holder.addCallback(new SurfaceHolder.Callback() { /* 当SurfaceView创建时候调用 */ @Override public void surfaceCreated(SurfaceHolder surfaceHolder) { /* 设置当前surfaceview为相机的显示区域 */ try { if (mCamera != null) mCamera.setPreviewDisplay(surfaceHolder); } catch (IOException e) { Log.e(TAG_CAMERA, "surfaceView fail..."); e.printStackTrace(); } } /* 首次显示到屏幕是调用的方法 */ @Override public void surfaceChanged(SurfaceHolder surfaceHolder, int i, int i1, int i2) { if(mCamera == null) return; try { /* 开始绘制帧 */ mCamera.startPreview(); } catch (Exception e) { Log.e(TAG_CAMERA, "camera start preview fail..."); mCamera.release(); mCamera = null; e.printStackTrace(); } } /* 当SurfaceView从屏幕上移除时 */ @Override public void surfaceDestroyed(SurfaceHolder surfaceHolder) { /* 设置相机不再在这个域显示 */ if (mCamera != null) /* 停止绘制帧 */ mCamera.stopPreview(); } });
实现相机的回调方法
捕获图像,并存为JPEG图片。
public final void takePicture(Camera.ShutterCallback shutter, Camera.PictureCallback raw, Camera.PictureCallback jpeg);
- ShutterCallback回调方法在相机捕获图片时调用。此时图像数据还没有完成。
- PictureCallback raw,原始数据可用时调用的回调函数。
- PicryreCallback jpeg,在jpeg版本的图像可用时调用的回调函数。
下面就是两个接口ShutterCallback,PictureCallbak的实现:
private Camera.ShutterCallback mShutterCallback = new Camera.ShutterCallback() { @Override public void onShutter() { mProgressBarContainer.setVisibility(View.VISIBLE); } }; private Camera.PictureCallback mJpegCallback = new Camera.PictureCallback() { @Override public void onPictureTaken(byte[] bytes, Camera camera) { /* 随机生成一个文件名 */ String fileName = UUID.randomUUID().toString() + ".jpg"; /* 创建一个文件输出流,生成jpeg文件 */ FileOutputStream os = null; boolean success = true; try { os = getActivity().openFileOutput(fileName, Context.MODE_PRIVATE); os.write(bytes); } catch (IOException e) { success = false; e.printStackTrace(); } finally { try { if (os != null) os.close(); } catch (IOException e) { success = false; e.printStackTrace(); } } if(success) { //Log.d(TAG_CAMERA, "save picture " + fileName + " success."); /* 返回生成的文件名给父Activity */ Intent i = new Intent(); i.putExtra(EXTRA_PHOTO, fileName); getActivity().setResult(Activity.RESULT_OK, i); } else getActivity().setResult(Activity.RESULT_CANCELED); /* 关闭拍照界面 */ getActivity().finish(); } };
拍照功能的实现是在拍照按钮的监听器事件中触发的:
mTakePhoto = (Button) v.findViewById(R.id.camera_take_photo); mTakePhoto.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View view) { if(mCamera != null) /* 这里只处理生成jpeg图像后的事件 */ mCamera.takePicture(mShutterCallback, null, mJpegCallback); } });
图片处理与显示
图片显示可以使用ImageView视图:
<ImageView android:id="@+id/imageView" android:layout_width="80dp" android:layout_height="80dp" android:scaleType="centerInside" android:cropToPadding="true"/>
由于现在的图片的尺寸都是比较大的,一般我们在显示图片之前都会对图片进行处理。接下来就是一个类来适当的缩放图片尺寸来适合在ImageView中的显示。
import android.app.Activity; import android.graphics.Bitmap; import android.graphics.BitmapFactory; import android.graphics.drawable.BitmapDrawable; import android.view.Display; import android.widget.ImageView; public class PictureUtils { /* 获取适当尺寸的图片大小,path为图片文字路径 */ public static BitmapDrawable getScaledDrawble(Activity a, String path){ Display display = a.getWindowManager().getDefaultDisplay(); float desWidth = display.getWidth(); float desHeight = display.getHeight(); BitmapFactory.Options options = new BitmapFactory.Options(); options.inJustDecodeBounds = true; BitmapFactory.decodeFile(path, options); float srcWidth = options.outWidth; float srcHeight = options.outHeight; int scaleSize = 1; if(srcWidth > desWidth || srcHeight > desHeight){ if(srcWidth > srcHeight) scaleSize = Math.round(srcHeight/desHeight); else scaleSize = Math.round(srcWidth/desWidth); } options = new BitmapFactory.Options(); options.inSampleSize = scaleSize; Bitmap bitmap = BitmapFactory.decodeFile(path, options); return new BitmapDrawable(a.getResources(), bitmap); } /* 回收ImageView对象中图像数据 */ public static void cleanImageView(ImageView imageView){ if(!(imageView.getDrawable() instanceof BitmapDrawable)) return; BitmapDrawable b = (BitmapDrawable) imageView.getDrawable(); b.getBitmap().recycle(); imageView.setImageDrawable(null); } }
然后就是把处理后的图片显示到ImageView上。
public void showPhoto(){ String path = ...; BitmapDrawable b = PictureUtils.getScaledDrawble(getActivity(), path); mImageView.setImageDrawable(b); }
- 安卓开发——相机:拍照并处理图片
- 安卓项目SimpleQQ——拍照并保存图片到本地
- Android启动相机拍照并返回图片
- Android启动相机拍照并返回图片
- 安卓开发,从相册或者相机中选择一张图片并裁剪,上传和下载。
- Android 拍照以及一些常用的处理,例如将图片显示到相册(包含了安卓系统6.0以上调用相机的处理)
- Android开发——相册拍照_03.解决相机拍照之后部分手机无法将图片保存到路径或部分手机点击相机确定无法返回问题
- 安卓拍照,并对照片进行简单处理
- Android调用安卓相机拍照上传
- 安卓调用系统相机拍照
- 安卓 自定义相机,身份证拍照
- 安卓,弹出选项框从相册相机中选择图片并显示。动态权限的处理,附源代码。
- 安卓拍照并裁剪
- 调用相机拍照,处理图片旋转,保存图片
- 安卓开发之自定义相机时图片变形问题
- 从相册,相机拍照,并对图片进行剪裁
- Android调用系统相机拍照并保存图片文件
- android 打开系统相机拍照并保存文件,显示图片。
- BLE-NRF51822教程10-手机动态修改设备名
- windows下删除所有 .svn文件及文件夹
- HTML5+CSS3 权威指南读书笔记
- Camera.Parameters 参数
- Objective-C简介
- 安卓开发——相机:拍照并处理图片
- js之惰性函数
- 微信支付问题
- 搭建 React Native 开发环境
- laravel安装
- HDU 1249 三角形【递推】
- uva 10404 Bachet's Game
- iOS--UITabbarController自定义
- 【数据结构学习笔记】——根据中缀表达式构建二叉树并输出