Android开发仿扫一扫实现拍摄框内的照片功能
程序员文章站
2024-03-05 11:32:06
就是仿照现在扫一扫的形式,周围是半透明的遮挡,然后中间是全透明的,拍摄后只截取框内的内容
查了很多博客,实现起来真的太复杂了,本人比较怕麻烦所以在很多地方偷懒了...
就是仿照现在扫一扫的形式,周围是半透明的遮挡,然后中间是全透明的,拍摄后只截取框内的内容
查了很多博客,实现起来真的太复杂了,本人比较怕麻烦所以在很多地方偷懒了
先上效果图:
第一步:设置照相机预览以及拍照
这是所有步骤的前提,没有预览,用户怎么知道自己拍的什么呢。预览用的是surfaceview
这篇博文写得已经十分详细了,打开照相机,然后拍照,而且十分简洁!不想别的博客一下就几百行代码不知所云。这篇代码可以复制下去当相机模版使用。
这里遇到一个问题,就是预览的效果是左转90度的,拍出来也是左转90度的,查了很多资料,大家统一的做法就是。在相机预览那里设置右旋90度,拍下的照片再右旋90度,具体的做法我会贴代码
第二步:设置半透明边框
很多博客的做法是绘图呀什么的,太过负责。
其实如果考虑简单点的话,只要在surfaceview上面叠加一层图片就好了,用framelayout布局
就是背景半透明,中间扣掉
第三步:怎么只拍摄框内的图片
这个问题,很多博客都是长篇大论,什么矩阵运算都用上了,虽然很强,但是不想看下去。
拍摄框内的图片,就直接拍完整张照片之后,在照片里面抠图就好了啊。
bitmap.createbitmap(bitmap,50,250,650,500);
自己算一下透明框大概在什么位置,左上角的坐标是什么,宽和高是什么。用上述函数就可以在原照片抠图了。
第四步:完善一点,加入点击对焦
其实就是在点击事件里面调用对焦函数就行
总的代码:
public class mainactivity extends appcompatactivity { private surfaceview surfaceview; private camera camera; private button take; @override protected void oncreate(bundle savedinstancestate) { super.oncreate(savedinstancestate); requestwindowfeature(window.feature_no_title); // 没有标题 必须在设置布局之前找到调用 setcontentview(r.layout.activity_main); /* getwindow().setflags(windowmanager.layoutparams.flag_fullscreen, // 设置全屏显示 windowmanager.layoutparams.flag_fullscreen); */ take = (button)findviewbyid(r.id.take); surfaceview = (surfaceview) findviewbyid(r.id.surfaceview); surfaceholder holder = surfaceview.getholder(); holder.setfixedsize(176, 155);// 设置分辨率 holder.setkeepscreenon(true); holder.settype(surfaceholder.surface_type_push_buffers); // surfaceview只有当activity显示到了前台,该控件才会被创建 因此需要监听surfaceview的创建 holder.addcallback(new mysurfacecallback()); //拍照按钮 take.setonclicklistener(new view.onclicklistener() { @override public void onclick(view view) { takepicture(); } }); } //点击事件 @override public boolean ontouchevent(motionevent event) { //对焦 camera.autofocus(new camera.autofocuscallback() { @override public void onautofocus(boolean b, camera camera) { camera.cancelautofocus(); } }); return super.ontouchevent(event); } /** * 监听surfaceview的创建 * @author administrator * surfaceview只有当activity显示到前台,该空间才会被创建 */ private final class mysurfacecallback implements surfaceholder.callback { @override public void surfacechanged(surfaceholder holder, int format, int width, int height) { // todo auto-generated method stub } @override public void surfacecreated(surfaceholder holder) { // todo auto-generated method stub try { // 当surfaceview创建就去打开相机 camera = camera.open(); camera.parameters params = camera.getparameters(); // log.i("i", params.flatten()); params.setjpegquality(80); // 设置照片的质量 params.setpicturesize(1024, 768); params.setpreviewframerate(5); // 预览帧率 camera.setparameters(params); // 将参数设置给相机 //右旋90度,将预览调正 camera.setdisplayorientation(90); // 设置预览显示 camera.setpreviewdisplay(surfaceview.getholder()); // 开启预览 camera.startpreview(); } catch (ioexception e) { // todo auto-generated catch block e.printstacktrace(); } } @override public void surfacedestroyed(surfaceholder holder) { // todo auto-generated method stub if(camera != null){ camera.release(); camera = null; } } } //拍照的函数 public void takepicture(){ /* * shutter:快门被按下 * raw:相机所捕获的原始数据 * jpeg:相机处理的数据 */ camera.takepicture(null, null, new mypicturecallback()); } //byte转bitmap public bitmap bytes2bimap(byte[] b) { if (b.length != 0) { return bitmapfactory.decodebytearray(b, 0, b.length); } else { return null; } } //bitmap转byte public byte[] bitmap2bytes(bitmap bm) { bytearrayoutputstream baos = new bytearrayoutputstream(); bm.compress(bitmap.compressformat.png, 100, baos); return baos.tobytearray(); } //照片回调函数,其实是处理照片的 private final class mypicturecallback implements camera.picturecallback { @override public void onpicturetaken(byte[] data, camera camera) { // todo auto-generated method stub try { bitmap bitmap = bytes2bimap(data); matrix m = new matrix(); int width = bitmap.getwidth(); int height = bitmap.getheight(); m.setrotate(90); //将照片右旋90度 bitmap = bitmap.createbitmap(bitmap, 0, 0, width, height, m, true); log.d("tag","width "+width); log.d("tag","height "+height); //截取透明框内照片 bitmap = bitmap.createbitmap(bitmap,50,250,650,500); data = bitmap2bytes(bitmap); file file = new file(environment.getexternalstoragedirectory(),system.currenttimemillis()+".jpg"); fileoutputstream fos = new fileoutputstream(file); fos.write(data); // 在拍照的时候相机是被占用的,拍照之后需要重新预览 camera.startpreview(); } catch (exception e) { // todo auto-generated catch block e.printstacktrace(); } } } }
以上所述是小编给大家介绍的android开发仿扫一扫实现拍摄框内的照片功能 ,希望对大家有所帮助