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

原创 2013年02月13日 11:54:23

【后注:】下载代码的注意,我的手机是4.3寸的屏,华为U9200.如果不能运行的请修改参数。看前文的第四条。Y的,省的说我传的代码不能用发火 

 

最近一直在审视以前做过的东西,关于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种方法愣是无济于事。我擦。。。如果有高人,希望能不吝指点下。 不过说实话,人家已经设计出来的产品界面看着就是好,不得不服阿。以后要多多模仿钻研这些成型产品的设计。

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

欢迎android爱好者加群248217350,备注:yanzi

                                                                     ----------------------------------------本文系原创,转载请注明作者:yanzi1225627

    

Android自定义相机,带边框截图

参考:点击打开链接
  • yangsainan
  • yangsainan
  • 2014年10月30日 15:09
  • 4737

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

杂家前文曾写过一篇关于只拍摄特定区域图片的demo,只是比较简陋,在坐标的换算上不是很严谨,而且没有完成预览界面四周暗中间亮的效果,深以为憾,今天把这个补齐了。 在上代码之前首先交代下,这里面存在着换...
  • yanzi1225627
  • yanzi1225627
  • 2014年06月26日 22:29
  • 23658

如何为自定义相机添加 取景框|扫描框 |预览框|矩形框

自定义 相机 及取景框 绘制 在相机预览组件上覆盖一层 自定义ImageView 重写 IamgeView的 ondraw() 方法。 2.要实现第一步 首先要的到矩形框 左上角的 坐标(全屏下是...
  • u013783167
  • u013783167
  • 2015年11月18日 20:33
  • 1832

android自定义相机带取景框

  • 2016年11月19日 19:54
  • 156KB
  • 下载

android自定义相机加取景框

1、首先,xml布局,两个控件。SurfaceView和MyView
  • ming_csdn_
  • ming_csdn_
  • 2017年04月05日 14:39
  • 1775

android动态取景框拍照实现源码

  • 2013年04月16日 10:14
  • 1000KB
  • 下载

Android SurfaceView的绘制详解

在Android系统中,有一种特殊的视图,称为SurfaceView,它拥有独立的绘图表面,即它不与其宿主窗口共享同一个绘图表面。由于拥有独立的绘图表面,因此SurfaceView的UI就可以在一个独...
  • aa841538513
  • aa841538513
  • 2016年08月23日 11:51
  • 6419

Android开发 摄像头SurfaceView预览 背景带矩形框 实现(原理:双surfaceview,顶层画矩形框,底层预览视频)

为了能在摄像头预览的时候,背景有个矩形框、或一些坐标、横线来标示关键位置,真让杂家费劲心思了。苦苦研究了两天,毫无进展。baidu了若干资料,大都是提出这个问题,但怎么解决的没有说,都不了了之。后来转...
  • yanzi1225627
  • yanzi1225627
  • 2012年09月02日 16:48
  • 41518

android 相机圆形,矩形拍照预览

首先,相机这块我也不是特别懂,之前也没开发过这块。参考了YanZi大神的文章http://blog.csdn.net/yanzi1225627/article/details/34931759不多说,...
  • wu244208909
  • wu244208909
  • 2016年08月25日 15:35
  • 769

android图片或拍照选取指定区域的 完美解决方案

  • 2013年09月24日 12:25
  • 117KB
  • 下载
内容举报
返回顶部
收藏助手
不良信息举报
您举报文章:Android摄像头:只拍摄SurfaceView预览界面特定区域内容(矩形框)---完整实现(原理:底层SurfaceView+上层绘制ImageView)
举报原因:
原因补充:

(最多只允许输入30个字)