Android开发仿扫一扫实现拍摄框内的照片功能
作者:wzben 发布时间:2023-03-17 14:11:12
标签:android,扫一扫
就是仿照现在扫一扫的形式,周围是半透明的遮挡,然后中间是全透明的,拍摄后只截取框内的内容
查了很多博客,实现起来真的太复杂了,本人比较怕麻烦所以在很多地方偷懒了
先上效果图:
第一步:设置照相机预览以及拍照
这是所有步骤的前提,没有预览,用户怎么知道自己拍的什么呢。预览用的是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开发仿扫一扫实现拍摄框内的照片功能 网站的支持!
来源:http://www.cnblogs.com/wzben/p/5888035.html


猜你喜欢
- 上篇博文:Java-多线程的使用equals与==1. ==的使用1.1 概述⭕ 用于基本类型比较值时:只要两个变量的值相等,即为true。
- 本文实例为大家分享了Android日历控件的使用方法,供大家参考,具体内容如下MainActivity.java代码:package sis
- 本文实例讲述了Java爬取豆瓣电影数据的方法。分享给大家供大家参考,具体如下:所用到的技术有Jsoup,HttpClient。Jsoupjs
- Android Studio + Gradle的组合用起来非常方便,很多第三方开源项目也早都迁移到了Studio,为此今天就来介绍下查看、编
- 本文介绍了浅谈Java的两种多线程实现方式,分享给大家。具有如下:一、创建多线程的两种方式Java中,有两种方式可以创建多线程:1 通过继承
- switch语句的格式如下:(它的功能是选出一段代码执行) switch(整数选择因子) { case 整数值1 : 语句; break;
- 目录课设要求相关知识点1.服务端能够看到所有在线用户2.服务端能够强制用户下线3.客户端能够看到所有在线用户4.客户端要求能够向某个用户发送
- 试用了Overt.Core.Grpc, 把 GRPC 的使用改造得像 WCF, 性能测试也非常不错, 非常推荐各位使用.但已有项目大多是 h
- Java单例模式的实现,对java 单例模式的几种实现方法进行了整理:单例模式好多书上都是这么写的:public class SingleT
- Lambda表达式的进化之路为什么要使用Lambda表达式可以简洁代码,提高代码的可读性可以避免匿名内部类定义过多导致逻辑紊乱在原先实现接口
- java中对集合对象list的几种循环访问的总结如下 1 经典的for循环 public static voi
- 前言:最近公司C轮融资成功了,移动团队准备扩大一下,需要招聘Android开发工程师,陆陆续续面试了几位Android应聘者,面试过程中聊到
- 1、局部变量在方法或语句块中定义的变量被称为局部变量。变量声明和初始化都是在方法中,方法结束后,变量就会自动销毁。局部变量声明在方法、构造方
- 一、 添加 maven 依赖<dependency> <groupId>com.google.guava
- 1. 定义栈:线程运行时需要的内存空间,一个栈存在多个栈帧。栈具有先入后出,后入先出的特点。栈帧:每个方法运行时需要的内存(局部变量表、操作
- 本文实例讲述了Android开发实现popupWindow弹出窗口自定义布局与位置控制方法。分享给大家供大家参考,具体如下:布局文件:主布局
- 在J2EE项目的开发中,不管是对底层的数据库操作过程,还是业务层的处理过程,还是控制层的处理过程,都不可避免会遇到各种可预知的、不可预知的异
- 首先项目A,也就是SpringBOOT项目中使用redisTemplate 来做REDIS的缓存时,你会发现存到REDIS里边的KEY和VA
- Scrollview标题栏滑动渐变仿京东样式(上滑显示下滑渐变消失)/** * @ClassName MyScrollView * @Aut
- C# 中可以将类、结构或接口的定义拆分到两个或多个源文件中,在类声明前添加partial关键字即可。1. 什么是局部类型?C# 2.0 引入