Android Camera+SurfaceView实现自己定义拍照
对Activity强制横屏,保证预览方向正确。
使用OrientationEventListener监听设备方向。推断竖拍时,旋转照片后再保存。保证竖拍时预览图片和保存后的图片方向一致。
执行效果:
代码:
TestCameraActivity.java
- package com.example.testcamera;
- import java.io.ByteArrayOutputStream;
- import java.io.FileOutputStream;
- import java.io.IOException;
- import java.util.List;
- import java.util.UUID;
- import android.annotation.SuppressLint;
- import android.app.Activity;
- import android.content.Context;
- import android.content.Intent;
- import android.graphics.Bitmap;
- import android.graphics.BitmapFactory;
- import android.graphics.Matrix;
- import android.hardware.Camera;
- import android.hardware.Camera.Parameters;
- import android.hardware.Camera.Size;
- import android.os.Build;
- import android.os.Bundle;
- import android.util.Log;
- import android.view.OrientationEventListener;
- import android.view.SurfaceHolder;
- import android.view.SurfaceView;
- import android.view.View;
- import android.view.View.OnClickListener;
- import android.widget.Button;
- public class TestCameraActivity extends Activity implements OnClickListener,
- SurfaceHolder.Callback {
- private static final String TAG = "TestCameraActivity";
- public static final String KEY_FILENAME = "filename";
- private Button mTakePhoto;
- private SurfaceView mSurfaceView;
- private Camera mCamera;
- private String mFileName;
- private OrientationEventListener mOrEventListener; // 设备方向监听器
- private Boolean mCurrentOrientation; // 当前设备方向 横屏false,竖屏true
- /* 图像数据处理还未完毕时的回调函数 */
- private Camera.ShutterCallback mShutter = new Camera.ShutterCallback() {
- @Override
- public void onShutter() {
- // 一般显示运行进度条
- }
- };
- /* 图像数据处理完毕后的回调函数 */
- private Camera.PictureCallback mJpeg = new Camera.PictureCallback() {
- @Override
- public void onPictureTaken(byte[] data, Camera camera) {
- // 保存图片
- mFileName = UUID.randomUUID().toString() + ".jpg";
- Log.i(TAG, mFileName);
- FileOutputStream out = null;
- try {
- out = openFileOutput(mFileName, Context.MODE_PRIVATE);
- byte[] newData = null;
- if (mCurrentOrientation) {
- // 竖屏时。旋转图片再保存
- Bitmap oldBitmap = BitmapFactory.decodeByteArray(data, 0,
- data.length);
- Matrix matrix = new Matrix();
- matrix.setRotate(90);
- Bitmap newBitmap = Bitmap.createBitmap(oldBitmap, 0, 0,
- oldBitmap.getWidth(), oldBitmap.getHeight(),
- matrix, true);
- ByteArrayOutputStream baos = new ByteArrayOutputStream();
- newBitmap.compress(Bitmap.CompressFormat.JPEG, 85, baos);
- newData = baos.toByteArray();
- out.write(newData);
- } else {
- out.write(data);
- }
- } catch (IOException e) {
- e.printStackTrace();
- } finally {
- try {
- if (out != null)
- out.close();
- } catch (IOException e) {
- e.printStackTrace();
- }
- }
- Intent i = new Intent(TestCameraActivity.this, ShowPicture.class);
- i.putExtra(KEY_FILENAME, mFileName);
- startActivity(i);
- finish();
- }
- };
- @SuppressWarnings("deprecation")
- @Override
- protected void onCreate(Bundle savedInstanceState) {
- super.onCreate(savedInstanceState);
- setContentView(R.layout.activity_test_camera);
- mTakePhoto = (Button) findViewById(R.id.take_photo);
- mTakePhoto.setOnClickListener(this); // 拍照button监听器
- startOrientationChangeListener(); // 启动设备方向监听器
- mSurfaceView = (SurfaceView) findViewById(R.id.my_surfaceView);
- SurfaceHolder holder = mSurfaceView.getHolder();
- holder.setType(SurfaceHolder.SURFACE_TYPE_PUSH_BUFFERS);
- holder.addCallback(this); // 回调接口
- }
- private final void startOrientationChangeListener() {
- mOrEventListener = new OrientationEventListener(this) {
- @Override
- public void onOrientationChanged(int rotation) {
- if (((rotation >= 0) && (rotation <= 45)) || (rotation >= 315)
- || ((rotation >= 135) && (rotation <= 225))) {// portrait
- mCurrentOrientation = true;
- Log.i(TAG, "竖屏");
- } else if (((rotation > 45) && (rotation < 135))
- || ((rotation > 225) && (rotation < 315))) {// landscape
- mCurrentOrientation = false;
- Log.i(TAG, "横屏");
- }
- }
- };
- mOrEventListener.enable();
- }
- @Override
- public void onClick(View v) {
- // 点击拍照
- switch (v.getId()) {
- case R.id.take_photo:
- mCamera.takePicture(mShutter, null, mJpeg);
- break;
- default:
- break;
- }
- }
- @Override
- public void surfaceChanged(SurfaceHolder holder, int format, int width,
- int height) {
- // SurfaceView尺寸发生改变时(首次在屏幕上显示相同会调用此方法)。初始化mCamera參数,启动Camera预览
- Parameters parameters = mCamera.getParameters();// 获取mCamera的參数对象
- Size largestSize = getBestSupportedSize(parameters
- .getSupportedPreviewSizes());
- parameters.setPreviewSize(largestSize.width, largestSize.height);// 设置预览图片尺寸
- largestSize = getBestSupportedSize(parameters
- .getSupportedPictureSizes());// 设置捕捉图片尺寸
- parameters.setPictureSize(largestSize.width, largestSize.height);
- mCamera.setParameters(parameters);
- try {
- mCamera.startPreview();
- } catch (Exception e) {
- if (mCamera != null) {
- mCamera.release();
- mCamera = null;
- }
- }
- }
- @Override
- public void surfaceCreated(SurfaceHolder holder) {
- // SurfaceView创建时,建立Camera和SurfaceView的联系
- if (mCamera != null) {
- try {
- mCamera.setPreviewDisplay(holder);
- } catch (IOException e) {
- e.printStackTrace();
- }
- }
- }
- @Override
- public void surfaceDestroyed(SurfaceHolder holder) {
- // SurfaceView销毁时。取消Camera预览
- if (mCamera != null) {
- mCamera.stopPreview();
- }
- }
- @SuppressLint("NewApi")
- @Override
- public void onResume() {
- super.onResume();
- // 开启相机
- if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.GINGERBREAD) {
- mCamera = Camera.open(0);
- // i=0 表示后置相机
- } else
- mCamera = Camera.open();
- }
- @Override
- public void onPause() {
- super.onPause();
- // 释放相机
- if (mCamera != null) {
- mCamera.release();
- mCamera = null;
- }
- }
- private Size getBestSupportedSize(List<Size> sizes) {
- // 取能适用的最大的SIZE
- Size largestSize = sizes.get(0);
- int largestArea = sizes.get(0).height * sizes.get(0).width;
- for (Size s : sizes) {
- int area = s.width * s.height;
- if (area > largestArea) {
- largestArea = area;
- largestSize = s;
- }
- }
- return largestSize;
- }
- }
ShowPicture.java
- package com.example.testcamera;
- import android.app.Activity;
- import android.graphics.Bitmap;
- import android.graphics.BitmapFactory;
- import android.graphics.drawable.BitmapDrawable;
- import android.os.Bundle;
- import android.util.Log;
- import android.view.Display;
- import android.widget.ImageView;
- public class ShowPicture extends Activity {
- private static final String TAG = "ShowPicture";
- private ImageView mPicture;
- public void onCreate(Bundle savedInstanceState) {
- super.onCreate(savedInstanceState);
- setContentView(R.layout.activity_show_picture);
- mPicture = (ImageView) findViewById(R.id.picture);
- String fileName = getIntent().getStringExtra(
- TestCameraActivity.KEY_FILENAME);
- // 图片路径
- Log.i(TAG, fileName);
- String path = getFileStreamPath(fileName).getAbsolutePath();
- Display display = getWindowManager().getDefaultDisplay(); // 显示屏尺寸
- float destWidth = display.getWidth();
- float destHeight = display.getHeight();
- // 读取本地图片尺寸
- BitmapFactory.Options options = new BitmapFactory.Options();
- options.inJustDecodeBounds = true;
- BitmapFactory.decodeFile(path, options);// 设置为true,options依旧相应此图片,但解码器不会为此图片分配内存
- float srcWidth = options.outWidth;
- float srcHeight = options.outHeight;
- int inSampleSize = 1;
- if (srcHeight > destHeight || srcWidth > destWidth) { // 当图片长宽大于屏幕长宽时
- if (srcWidth > srcHeight) {
- inSampleSize = Math.round(srcHeight / destHeight);
- } else {
- inSampleSize = Math.round(srcWidth / destWidth);
- }
- }
- options = new BitmapFactory.Options();
- options.inSampleSize = inSampleSize;
- Bitmap bitmap = BitmapFactory.decodeFile(path, options);
- BitmapDrawable bDrawable = new BitmapDrawable(getResources(), bitmap);
- mPicture.setImageDrawable(bDrawable);
- }
- @Override
- public void onDestroy() {
- if (!(mPicture.getDrawable() instanceof BitmapDrawable))
- return;
- // 释放bitmap占用的空间
- BitmapDrawable b = (BitmapDrawable) mPicture.getDrawable();
- b.getBitmap().recycle();
- mPicture.setImageDrawable(null);
- }
- }
Android Camera+SurfaceView实现自己定义拍照的更多相关文章
- 玩转Android Camera开发(一):Surfaceview预览Camera,基础拍照功能完整demo
杂家前文是在2012年的除夕之夜仓促完成,后来很多人指出了一些问题,琐事缠身一直没有进行升级.后来随着我自己的使用,越来越发现不出个升级版的demo是不行了.有时候就连我自己用这个demo测一些性能. ...
- Android Camera进行拍照
Android应用提供了Camera来控制拍照,使用Camera进行拍照的步骤: 1.调用Camera的open()方法打开相机. 2.调用Camera的getParameters()方法获取拍照参数 ...
- Android 举例说明自己的定义Camera图片和预览,以及前后摄像头切换
如何调用本地图片,并调用系统拍摄的图像上一博文解释(http://blog.csdn.net/a123demi/article/details/40003695)的功能. 而本博文将通过实例实现自己定 ...
- Android Camera开发系列(下)——自定义Camera实现拍照查看图片等功能
Android Camera开发系列(下)--自定义Camera实现拍照查看图片等功能 Android Camera开发系列(上)--Camera的基本调用与实现拍照功能以及获取拍照图片加载大图片 上 ...
- 玩转Android Camera开发(二):使用TextureView和SurfaceTexture预览Camera 基础拍照demo
Google自Android4.0出了TextureView,为什么推出呢?就是为了弥补Surfaceview的不足,另外一方面也是为了平衡GlSurfaceView,当然这是本人揣度的.关于Text ...
- Android Camera开发:使用TextureView和SurfaceTexture预览Camera 基础拍照demo
Google自Android4.0出了TextureView,为什么推出呢?就是为了弥补Surfaceview的不足,另外一方面也是为了平衡GlSurfaceView,当然这是本人揣度的.关于Text ...
- Android Camera相机功能实现 拍照并保存图片
AndroidManifest.xml <uses-feature android:name="android.hardware.camera"/> <uses- ...
- Android Camera开发系列(上)——Camera的基本调用与实现拍照功能以及获取拍照图片加载大图片
Android Camera开发系列(上)--Camera的基本调用与实现拍照功能以及获取拍照图片加载大图片 最近也是在搞个破相机,兼容性那叫一个不忍直视啊,于是自己翻阅了一些基本的资料,自己实现了一 ...
- Android Camera 拍照 三星BUG总结
Android Camera 三星BUG : 近期在Android项目中使用拍照功能 , 其他型号的手机执行成功了 只有在三星的相机上遇到了bug . BUG详细体现为 : (1) 摄像头拍照后图 ...
随机推荐
- (转)redis源代码分析 – event library
每个cs程序尤其是高并发的网络服务端程序都有自己的网络异步事件处理库,redis不例外. 事件库仅仅包括ae.c.ae.h,还有3个不同的多路复用(本文仅描述epoll)的wrapper文件,事件库封 ...
- COGS——T 2739. 凯伦和咖啡
http://www.cogs.pro/cogs/problem/problem.php?pid=2739 ★★☆ 输入文件:coffee.in 输出文件:coffee.out 简单对比时 ...
- 洛谷——T P2136 拉近距离
https://www.luogu.org/problem/show?pid=2136 题目背景 我是源点,你是终点.我们之间有负权环. ——小明 题目描述 在小明和小红的生活中,有N个关键的节点.有 ...
- Qt之设置应用程序图标
简述 应用程序图标,通常显示在应用程序的顶层窗口的左上角,通过调用QWindow:setWindowIcon()函数来实现. 为了改变可执行程序文件本身的图标,因为它被呈现在桌面上,它必须采用另一种依 ...
- HDU 4320 Contest 3
只需A的全部质因数包含在B中即可. #include <iostream> #include <cstdio> #define LL __int64 #include < ...
- linux文件与用户和群组
文件基本属性 在图片中alogrithm的文件属性为drwxrwxr-x,其中d代表此文件为目录. 后面rwx,rwx,r-x分别代表文件所属者(ower),组(group),其他用户(other)的 ...
- Ubuntu: GlusterFS+HBase安装教程
HBase通常安装在Hadoop HDFS上,但也能够安装在其它实现了Hadoop文件接口的分布式文件系统上.如KFS. glusterfs是一个集群文件系统可扩展到几peta-bytes. 它集合了 ...
- 使用C++实现学生管理系统
我在前面的博客中分别使用C语言的动态数组和链表实现了学生成绩管理系统.近期正好在学习C++,于是我便使用C++实现了学生成绩管理系统.算法和前面的C语言的动态数组实现的学生成绩管理系统几乎相同,仅仅是 ...
- iOS-MBProgressHUD使用
在码代码过程中,我们经常用到MBProgressHUD,但我很少实例化使用,一般都是偷个懒直接显示隐藏,这里贴上详解,以便日后有样式要求时使用. 1,MBProgressHUD常用属性和用法Demo ...
- hdoj--1260--Tickets(简单dp)
Tickets Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 65536/32768 K (Java/Others) Total Su ...