Android摄像头:只拍摄SurfaceView预览界面特定区域内容(矩形框)---完整(原理:底层SurfaceView+上层绘制ImageView)
http://blog.csdn.net/yanzi1225627/article/details/8580034
最近一直在审视以前做过的东西,关于android摄像头预览,预览界面上呈现矩形框,在前文(
Android开发 摄像头SurfaceView预览 背景带矩形框 实现(原理:双surfaceview,顶层画矩形框,底层预览视频)
)----http://blog.csdn.net/yanzi1225627/article/details/7934710已经实现。最近发现上层绘制矩形框,用surfaceview有点大材小用了。SurfaceView绘制动画更合适,只绘制个矩形框用ImageView足够了。但有些时候必须要用SurfaceView来实现。比如360手机安全卫士扫描二维码的实现应该就是通过上下两层SurfaceView实现的(见下图)。上层SurfaceView用于显示那个可以旋转的扫描示意框,底层SurfaceView预览摄像头视频。
废话不说了,稍候几天我会仿照上面360这个扫描二维码的界面做一个工程(结合PreviewCallback),公开出来。这次先谈用底层surfaceView+上层ImageView实现只拍摄矩形框中的图像。新建一个类继承ImageView,源码如下:
- package yan.guoqi.rectphoto;
- import android.content.Context;
- import android.graphics.Canvas;
- import android.graphics.Color;
- import android.graphics.Paint;
- import android.graphics.Paint.Style;
- import android.graphics.Rect;
- import android.util.AttributeSet;
- import android.widget.ImageView;
- public class DrawImageView extends ImageView{
- public DrawImageView(Context context, AttributeSet attrs) {
- super(context, attrs);
- // TODO Auto-generated constructor stub
- }
- Paint paint = new Paint();
- {
- paint.setAntiAlias(true);
- paint.setColor(Color.RED);
- paint.setStyle(Style.STROKE);
- paint.setStrokeWidth(2.5f);//设置线宽
- paint.setAlpha(100);
- };
- @Override
- protected void onDraw(Canvas canvas) {
- // TODO Auto-generated method stub
- super.onDraw(canvas);
- canvas.drawRect(new Rect(100, 200, 400, 500), paint);//绘制矩形
- }
- }
布局文件里与前文http://blog.csdn.net/yanzi1225627/article/details/8577756这里一样,只是在帧布局里加一个上面自定义的DrawImageView,整个布局文件示下:
- <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
- xmlns:tools="http://schemas.android.com/tools"
- android:layout_width="fill_parent"
- android:layout_height="fill_parent"
- android:orientation="vertical" >
- <TextView
- android:layout_width="wrap_content"
- android:layout_height="wrap_content"
- android:text="@string/BestWish"
- tools:context=".RectPhoto" />
- <FrameLayout
- android:layout_width="wrap_content"
- android:layout_height="wrap_content" >
- <SurfaceView
- android:id="@+id/previewSV"
- android:layout_width="fill_parent"
- android:layout_height="800px" />
- <yan.guoqi.rectphoto.DrawImageView
- android:id="@+id/drawIV"
- android:layout_width="fill_parent"
- android:layout_height="800px"
- />
- </FrameLayout>
- <ImageButton
- android:id="@+id/photoImgBtn"
- android:layout_width="wrap_content"
- android:layout_height="wrap_content"
- android:background="@drawable/photo_img_btn"
- android:layout_gravity="center" />
- </LinearLayout>
在主程序文件里,onCreate()函数里设置底层SurfaceView为底层且透明(如果不设也可以,默认就是如此):
mPreviewSV.setZOrderOnTop(false);
mySurfaceHolder.setFormat(PixelFormat.TRANSPARENT);//translucent半透明 transparent透明
在主UI线程里的onCreate()函数里添加代码:
//绘制矩形的ImageView
mDrawIV = (yan.guoqi.rectphoto.DrawImageView)findViewById(R.id.drawIV);
mDrawIV.onDraw(new Canvas());
看上面的DrawImageView的函数里的onDraw,画的矩形是Rect(100, 200, 400, 500)。在onPictureTaken(byte[] data, Camera camera)函数里,先将图片旋转90度,大小成为宽×高(960×1280)。由于预览surfaceview的大小是宽×高(540×800),所以在onPictureTaken函数里将960×1280的图片缩放到540×800, 缩放相同大小后就可以用矩阵的坐标直接截取子图了。核心函数就是这两句:
//将960×1280缩放到540×800
Bitmap sizeBitmap = Bitmap.createScaledBitmap(rotaBitmap, 540, 800, true);
Bitmap rectBitmap = Bitmap.createBitmap(sizeBitmap, 100, 200, 300, 300);//截取
注意这个截取的函数参数和矩阵的坐标关系,分别是x轴 y轴起始坐标及 x轴宽度 y轴宽度。截取出来的图片大小应该是300×300. onPictureTaken()函数的源码如下:
- public void onPictureTaken(byte[] data, Camera camera) {
- // TODO Auto-generated method stub
- Log.i(tag, "myJpegCallback:onPictureTaken...");
- if(null != data){
- mBitmap = BitmapFactory.decodeByteArray(data, 0, data.length);//data是字节数据,将其解析成位图
- myCamera.stopPreview();
- isPreview = false;
- }
- //设置FOCUS_MODE_CONTINUOUS_VIDEO)之后,myParam.set("rotation", 90)失效。图片竟然不能旋转了,故这里要旋转下
- Matrix matrix = new Matrix();
- matrix.postRotate((float)90.0);
- Bitmap rotaBitmap = Bitmap.createBitmap(mBitmap, 0, 0, mBitmap.getWidth(), mBitmap.getHeight(), matrix, false);
- //旋转后rotaBitmap是960×1280.预览surfaview的大小是540×800
- //将960×1280缩放到540×800
- Bitmap sizeBitmap = Bitmap.createScaledBitmap(rotaBitmap, 540, 800, true);
- Bitmap rectBitmap = Bitmap.createBitmap(sizeBitmap, 100, 200, 300, 300);//截取
- //保存图片到sdcard
- if(null != rectBitmap)
- {
- saveJpeg(rectBitmap);
- }
- //再次进入预览
- myCamera.startPreview();
- isPreview = true;
- }
涉及到的其他函数如saveJpeg()参见前文:
2013新春奉送:Android摄像头开发完美demo---(循环聚焦,缩放大小,旋转picture,查询支持的picturesize, ImageButton按键效果)------------
http://blog.csdn.net/yanzi1225627/article/details/8577756 重复的东西我就不发了。
效果图如下所示:
点击拍照,查看保存后的图片如下:
反思:
1,SurfaceView为啥 无论translucent半透明还是 transparent透明基本没啥区别?而且surfaceview的setAlpha函数不能用。
2,在这里surfaceview一定要在底层(默认如此),如果设成顶层会看不到红色矩形框。可以自己测试下。
3,最纠结的一点,第一副图片里的360扫描二维码的界面,底层的预览surfaceview是半透明的,底色是灰色的,只有中间的扫描矩形框是透明的,亮色。这一块究竟是怎么实现的??下午实验了n种方法愣是无济于事。我擦。。。如果有高人,希望能不吝指点下。 不过说实话,人家已经设计出来的产品界面看着就是好,不得不服阿。以后要多多模仿钻研这些成型产品的设计。
Android摄像头:只拍摄SurfaceView预览界面特定区域内容(矩形框)---完整(原理:底层SurfaceView+上层绘制ImageView)的更多相关文章
- 玩转Android Camera开发(四):预览界面四周暗中间亮,仅仅拍摄矩形区域图片(附完整源代码)
杂家前文曾写过一篇关于仅仅拍摄特定区域图片的demo.仅仅是比較简陋.在坐标的换算上不是非常严谨,并且没有完毕预览界面四周暗中间亮的效果,深以为憾.今天把这个补齐了. 在上代码之前首先交代下,这里面存 ...
- 玩转Android Camera开发(一):Surfaceview预览Camera,基础拍照功能完整demo
杂家前文是在2012年的除夕之夜仓促完成,后来很多人指出了一些问题,琐事缠身一直没有进行升级.后来随着我自己的使用,越来越发现不出个升级版的demo是不行了.有时候就连我自己用这个demo测一些性能. ...
- Android Camera2采集摄像头原始数据并手动预览
Android Camera2采集摄像头原始数据并手动预览 最近研究了一下android摄像头开发相关的技术,也看了Google提供的Camera2Basic调用示例,以及网上一部分代码,但都是在Te ...
- Android流媒体开发之路一:Camera2采集摄像头原始数据并手动预览
Android Camera2采集摄像头原始数据并手动预览 最近研究了一下android摄像头开发相关的技术,也看了Google提供的Camera2Basic调用示例,以及网上一部分代码,但都是在Te ...
- Android Camera开发:使用GLSurfaceView预览Camera 基础拍照
GLSurfaceView是OpenGL中的一个类,也是可以预览Camera的,而且在预览Camera上有其独到之处.独到之处在哪?当使用Surfaceview无能为力.痛不欲生时就只有使用GLSur ...
- 关于 pyspider Web预览界面太小的解决方法
本人最近在学习pyspider时,遇到Web预览界面太小而无法很好的进行开发,于是在网上搜索解决方法. 准备: css代码: body{margin:;padding:;height:%;overfl ...
- LODOP中预览界面查看打印机的可打区域具体值
LODOP在打印预览的时候,如果选择的打印机是真实打印机,会发现可能会有虚线,不同打印机虚线的位置不同,这个虚线是打印机的可打区域,Lodop无法控制. 可打区域,顾名思义,就是打印机可以打印的区域, ...
- [Swift通天遁地]九、拔剑吧-(12)创建Preview-Transition图像预览界面
★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★➤微信公众号:山青咏芝(shanqingyongzhi)➤博客园地址:山青咏芝(https://www.cnblogs. ...
- 怎样改动 VC6.0 4.0 2010 打印预览界面上的文字
前言:尽管早已下决心不再碰微软的东西,但手头的项目还得须要维护. 遇到问题还能解决. 问题由来: 之前的软件开发是基于中文环境开发的,建立项目的时候,选择了中文,为了方便客户使用.我们使用了静态编译的 ...
随机推荐
- awk 中 FS的用法
在openwrt文件 ar71xx.sh中 查询设备类型时,有这么一句, machine=$(awk 'BEGIN{FS="[ \t]+:[ \t]"} /machine/ {pr ...
- OpenGL 茶壶
void MyRenderer::Init_Teapot_VBO() { m_fun->glGenBuffers(, &m_teapot_vbo); m_fun->glBindBu ...
- Nimbus<二>storm启动nimbus源码分析-nimbus.clj
nimbus是storm集群的"控制器",是storm集群的重要组成部分.我们可以通用执行bin/storm nimbus >/dev/null 2>&1 &a ...
- 第二次冲刺spring会议(第一次会议)
[例会时间]2014/5/4 21:15 [例会地点]9#446 [例会形式]轮流发言 [例会主持]马翔 [例会记录]兰梦 小组成员:兰梦 ,马翔,李金吉,赵天,胡佳奇 内部测试版发布时间5月11日 ...
- WinSnap屏幕截图 V4.5.6 官方最新版
软件名称: WinSnap屏幕截图软件语言: 多国语言授权方式: 免费试用运行环境: Win7 / Vista / Win2003 / WinXP 软件大小: 2.7MB图片预览: 软件简介:WinS ...
- 网页 JavaScript
今天,我主要学习了JavaScript的部分内容. JavaScript在html中的位置主要有三个地方:head里面.body里面.</html>之后,我们一般写在</html&g ...
- 对http协议断点续传的理解
断点续传指的是下载传输文件可以中断,之后重新下载时可以接着中断的地方开始下载,而不必从头开始下载.断点续传需要客户端和服务端都支持. 原理是客户端一块一块的请求数据,最后将下载回来的数据块拼接成完整的 ...
- Python笔记2-20151023
一.循环 Python的循环有两种,一种是for...in循环,依次吧list或tuple中的每个元素迭代出来. >>>names = ['Michael','Bob','Tracy ...
- MediaWiki搭建教程
♦ MediaWiki是什么以及有什么作用,这里我就不再阐述了,网上可以查到很多.这里只是简单记录一下搭建wiki的基本过程,给一些热爱捯饬的小伙伴一些参考. ♦ 其实wiki的搭建本身很简单,最 ...
- 12C expdp issue
issue 1: 使用expdp时遭遇ora-31650 D:\oracle\diag\rdbms \trace>expdp \"/ as sysdba\" schemas ...