关闭 x
IT技术网
    技 采 号
    ITJS.cn - 技术改变世界
    • 实用工具
    • 菜鸟教程
    IT采购网 中国存储网 科技号 CIO智库

    IT技术网

    IT采购网
    • 首页
    • 行业资讯
    • 系统运维
      • 操作系统
        • Windows
        • Linux
        • Mac OS
      • 数据库
        • MySQL
        • Oracle
        • SQL Server
      • 网站建设
    • 人工智能
    • 半导体芯片
    • 笔记本电脑
    • 智能手机
    • 智能汽车
    • 编程语言
    IT技术网 - ITJS.CN
    首页 » 安卓开发 »Android Camera+SurfaceView实现自定义拍照

    Android Camera+SurfaceView实现自定义拍照

    2014-11-16 00:00:00 出处:eoeandroid
    分享

    对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); // 拍照按钮监听器
    
    		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);
    	}
    
    }

    源码下载

    上一篇返回首页 下一篇

    声明: 此文观点不代表本站立场;转载务必保留本文链接;版权疑问请联系我们。

    别人在看

    电脑屏幕不小心竖起来了?别慌,快捷键搞定

    Destoon 模板存放规则及语法参考

    Destoon系统常量与变量

    Destoon系统目录文件结构说明

    Destoon 系统安装指南

    Destoon会员公司主页模板风格添加方法

    Destoon 二次开发入门

    Microsoft 将于 2026 年 10 月终止对 Windows 11 SE 的支持

    Windows 11 存储感知如何设置?了解Windows 11 存储感知开启的好处

    Windows 11 24H2 更新灾难:系统升级了,SSD固态盘不见了...

    IT头条

    Synology 更新 ActiveProtect Manager 1.1 以增强企业网络弹性和合规性

    00:43

    新的 Rubrik Agent Cloud 加速了可信的企业 AI 代理部署

    00:34

    宇树科技 G1人形机器人,拉动一辆重达1.4吨的汽车

    00:21

    Cloudera 调查发现,96% 的企业已将 AI 集成到核心业务流程中,这表明 AI 已从竞争优势转变为强制性实践

    02:05

    投资者反对马斯克 1 万亿美元薪酬方案,要求重组特斯拉董事会

    01:18

    技术热点

    大型网站的 HTTPS 实践(三):基于协议和配置的优化

    ubuntu下右键菜单添加新建word、excel文档等快捷方式

    Sublime Text 简明教程

    用户定义SQL Server函数的描述

    怎么在windows 7开始菜单中添加下载选项?

    SQL Server 2016将有哪些功能改进?

      友情链接:
    • IT采购网
    • 科技号
    • 中国存储网
    • 存储网
    • 半导体联盟
    • 医疗软件网
    • 软件中国
    • ITbrand
    • 采购中国
    • CIO智库
    • 考研题库
    • 法务网
    • AI工具网
    • 电子芯片网
    • 安全库
    • 隐私保护
    • 版权申明
    • 联系我们
    IT技术网 版权所有 © 2020-2025,京ICP备14047533号-20,Power by OK设计网

    在上方输入关键词后,回车键 开始搜索。Esc键 取消该搜索窗口。