Android摄像头:只拍摄SurfaceView预览界面特定区域内容(矩形框)---完整(原理:底层SurfaceView+上层绘制ImageView)

Android摄像头:只拍摄SurfaceView预览界面特定区域内容(矩形框)---完整实现(原理:底层SurfaceView+上层绘制ImageView)

分类: Android开发 Android UI2013-05-23 15:04 1600人阅读 评论(1) 收藏 举报

目录(?)[+]

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,源码如下:

[java] view plaincopy

  1. package yan.guoqi.rectphoto;
  2. import android.content.Context;
  3. import android.graphics.Canvas;
  4. import android.graphics.Color;
  5. import android.graphics.Paint;
  6. import android.graphics.Paint.Style;
  7. import android.graphics.Rect;
  8. import android.util.AttributeSet;
  9. import android.widget.ImageView;
  10. public class DrawImageView extends ImageView{
  11. public DrawImageView(Context context, AttributeSet attrs) {
  12. super(context, attrs);
  13. // TODO Auto-generated constructor stub
  14. }
  15. Paint paint = new Paint();
  16. {
  17. paint.setAntiAlias(true);
  18. paint.setColor(Color.RED);
  19. paint.setStyle(Style.STROKE);
  20. paint.setStrokeWidth(2.5f);//设置线宽
  21. paint.setAlpha(100);
  22. };
  23. @Override
  24. protected void onDraw(Canvas canvas) {
  25. // TODO Auto-generated method stub
  26. super.onDraw(canvas);
  27. canvas.drawRect(new Rect(100, 200, 400, 500), paint);//绘制矩形
  28. }
  29. }

布局文件里与前文http://blog.csdn.net/yanzi1225627/article/details/8577756这里一样,只是在帧布局里加一个上面自定义的DrawImageView,整个布局文件示下:

[html] view plaincopy

  1. <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
  2. xmlns:tools="http://schemas.android.com/tools"
  3. android:layout_width="fill_parent"
  4. android:layout_height="fill_parent"
  5. android:orientation="vertical" >
  6. <TextView
  7. android:layout_width="wrap_content"
  8. android:layout_height="wrap_content"
  9. android:text="@string/BestWish"
  10. tools:context=".RectPhoto" />
  11. <FrameLayout
  12. android:layout_width="wrap_content"
  13. android:layout_height="wrap_content" >
  14. <SurfaceView
  15. android:id="@+id/previewSV"
  16. android:layout_width="fill_parent"
  17. android:layout_height="800px" />
  18. <yan.guoqi.rectphoto.DrawImageView
  19. android:id="@+id/drawIV"
  20. android:layout_width="fill_parent"
  21. android:layout_height="800px"
  22. />
  23. </FrameLayout>
  24. <ImageButton
  25. android:id="@+id/photoImgBtn"
  26. android:layout_width="wrap_content"
  27. android:layout_height="wrap_content"
  28. android:background="@drawable/photo_img_btn"
  29. android:layout_gravity="center" />
  30. </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()函数的源码如下:

[java] view plaincopy

  1. public void onPictureTaken(byte[] data, Camera camera) {
  2. // TODO Auto-generated method stub
  3. Log.i(tag, "myJpegCallback:onPictureTaken...");
  4. if(null != data){
  5. mBitmap = BitmapFactory.decodeByteArray(data, 0, data.length);//data是字节数据,将其解析成位图
  6. myCamera.stopPreview();
  7. isPreview = false;
  8. }
  9. //设置FOCUS_MODE_CONTINUOUS_VIDEO)之后,myParam.set("rotation", 90)失效。图片竟然不能旋转了,故这里要旋转下
  10. Matrix matrix = new Matrix();
  11. matrix.postRotate((float)90.0);
  12. Bitmap rotaBitmap = Bitmap.createBitmap(mBitmap, 0, 0, mBitmap.getWidth(), mBitmap.getHeight(), matrix, false);
  13. //旋转后rotaBitmap是960×1280.预览surfaview的大小是540×800
  14. //将960×1280缩放到540×800
  15. Bitmap sizeBitmap = Bitmap.createScaledBitmap(rotaBitmap, 540, 800, true);
  16. Bitmap rectBitmap = Bitmap.createBitmap(sizeBitmap, 100, 200, 300, 300);//截取
  17. //保存图片到sdcard
  18. if(null != rectBitmap)
  19. {
  20. saveJpeg(rectBitmap);
  21. }
  22. //再次进入预览
  23. myCamera.startPreview();
  24. isPreview = true;
  25. }

涉及到的其他函数如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种方法愣是无济于事。我擦。。。如果有高人,希望能不吝指点下。 不过说实话,人家已经设计出来的产品界面看着就是好,不得不服阿。以后要多多模仿钻研这些成型产品的设计。

源码下载:http://download.csdn.net/detail/yanzi1225627/5063105

时间: 2024-10-12 20:53:11

Android摄像头:只拍摄SurfaceView预览界面特定区域内容(矩形框)---完整(原理:底层SurfaceView+上层绘制ImageView)的相关文章

玩转Android Camera开发(四):预览界面四周暗中间亮,只拍摄矩形区域图片(附完整源码)

杂家前文曾写过一篇关于只拍摄特定区域图片的demo,只是比较简陋,在坐标的换算上不是很严谨,而且没有完成预览界面四周暗中间亮的效果,深以为憾,今天把这个补齐了. 在上代码之前首先交代下,这里面存在着换算的两种模式.第一种,是以屏幕上的矩形区域为基准进行换算.举个例子,屏幕中间一个 矩形框为100dip*100dip.这里一定要使用dip为单位,否则在不同的手机上屏幕呈现的矩形框大小不一样.先将这个dip换算成px,然后根据屏幕的宽和高的像素计算出矩形区域,传给Surfaceview上铺的一层Vi

玩转Android Camera开发(四):预览界面四周暗中间亮,仅仅拍摄矩形区域图片(附完整源代码)

杂家前文曾写过一篇关于仅仅拍摄特定区域图片的demo.仅仅是比較简陋.在坐标的换算上不是非常严谨,并且没有完毕预览界面四周暗中间亮的效果,深以为憾.今天把这个补齐了. 在上代码之前首先交代下,这里面存在着换算的两种模式.第一种,是以屏幕上的矩形区域为基准进行换算.举个样例.屏幕中间一个 矩形框为100dip*100dip.这里一定要使用dip为单位,否则在不同的手机上屏幕呈现的矩形框大小不一样. 先将这个dip换算成px.然后依据屏幕的宽和高的像素计算出矩形区域,传给Surfaceview上铺的

玩转Android Camera开发(一):Surfaceview预览Camera,基础拍照功能完整demo

杂家前文是在2012年的除夕之夜仓促完成,后来很多人指出了一些问题,琐事缠身一直没有进行升级.后来随着我自己的使用,越来越发现不出个升级版的demo是不行了.有时候就连我自己用这个demo测一些性能.功能点,用着都不顺手.当初代码是在linux下写的,弄到windows里下全是乱码.还要自己改几分钟才能改好.另外,很多人说不能正常预览,原因是我在布局里把Surfaceview的尺寸写死了.再有就是initCamera()的时候设参数失败,直接黑屏退出,原因也是我把预览尺寸和照片尺寸写死了.再有就

Android手势识别 Camera 预览界面上显示文字 布局注意事项(merge布局)

通常在Surfaceview作为预览视频帧的载体,有时需在上面显示提示文字.以前我弄的都好好的,今天忽然发现叠加的TextView不管咋弄都出不来文字了,跟Surfaceview一起放在FrameLayout也不行,后来想到merge布局,发现也不行.大爷的,奇了怪了,最后发现了原因,原来是顺序问题.也即无论是在RelativeLayout里还是merge布局里,View是逐个叠加上去的,一层一层铺上去的.如果你先放TextView在最前面,那肯定被后面的全屏Surfaceview覆盖了.用常规

Windows、Linux、ARM、Android、iOS全平台支持的RTMP推流组件EasyRTMP- iOS接入后,进入预览界面系统直接崩溃的原因分析

在接入EasyRTMP-iOS时,进入预览界面直接崩溃,是什么原因? 分析问题: iOS系统对于权限控制的很严格,因为预览需要用到相机权限.麦克风权限等,都需要向用户申请这些权限. 解决问题: 在Info.plist文件中,添加如下权限申明,并描述清楚您的用途: <key>NSCameraUsageDescription</key> <string>此App会在推送视频流时访问您的相机权限</string> <key>NSMicrophoneUs

android录制视屏(预览,倒计时)

android用mediarecord录制视屏,可以设置视屏格式,大小,还有拍摄前预览,倒计时功能要自己用hander做. 1,CameraPreview.java //预览class public class CameraPreview extends SurfaceView implements Callback { private static final String TAG = "TAG-CameraPreview"; private SurfaceHolder mHolde

如何修改 VC6.0 4.0 2010 打印预览界面上的文字

前言:虽然早已下决心不再碰微软的东西,但手头的项目还得需要维护.遇到问题还能解决. 问题由来: 之前的软件开发是基于中文环境开发的,建立项目的时候,选择了中文,为了方便客户使用,我们使用了静态编译的方法,这样用户用我们的软件就不用费尽心思的去装微软的库了,如此以来,像诸如调用"打印预览"功能时,界面上显示的是 "打印", "下一页"等全部是中文.后期需要做成其他语言的版本.我们自己开发的对话框全是以语言文件的格式来存放的,只需替换语言文件而不需要

Android的Studio 2.2 预览 - 新的UI设计师和约束布局

Android的Studio 2.2中预览 - 新的UI设计师和约束布局 由贾马尔-陈奕迅,产品经理,机器人 本周在谷歌I / O 2016年,我们推出Android Studio 2.2中预览.该版本是一个大的更新是建立在我们重点打造Android的快速和高效集成开发环境(IDE).与Android平台开发同步的Andr??oid Studio允许您使用最新的Andr??oid API和功能开发.由于只是3年前在谷歌I / O推出Android的工作室,我们从您对您最想要的什么功能,收到很好的

关于 pyspider Web预览界面太小的解决方法

本人最近在学习pyspider时,遇到Web预览界面太小而无法很好的进行开发,于是在网上搜索解决方法. 准备: css代码: body{margin:0;padding:0;height:100%;overflow:hidden}.warning{color:#f0ad4e}.error{color:#d9534f}#control{z-index:9999;min-width:760px;width:100%;height:35px;position:fixed;left:0;right:0;