转载自http://blog.csdn.net/jesse__zhong/article/details/24934083

使用双surface,将第一个设置为透明背景,在摄像机上绘制图像,纠结搞了一天。

其中参考了http://blog.csdn.net/yanzi1225627/article/details/7934710 的思路和代码,但是,始终会出现 canvas=holder.lockcanvas();返回的canvas为null的情况。加入线程后解决问题。

主Activity:

public class MainActivity extends Activity {

private SVDraw surfaceDraw = null;
private SurfaceView surfaceView = null;
private SurfaceHolder holder1 = null;
private Canvas canvas = null;
private Camera cam = null;
private boolean previewRunning = true;

@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);

//绘制surface1
  surfaceView = (SurfaceView) findViewById(R.id.surface1);
holder1 = surfaceView.getHolder();
holder1.addCallback(new MySurfaceViewCallback());
holder1.setType(SurfaceHolder.SURFACE_TYPE_PUSH_BUFFERS);
holder1.setFixedSize(500, 350);
holder1.setFormat(PixelFormat.TRANSPARENT);

canvas = holder1.lockCanvas();
if (canvas != null) {
canvas.drawColor(Color.TRANSPARENT);
Paint p = new Paint();
p.setAntiAlias(true);
p.setColor(Color.RED);
p.setStyle(Style.STROKE);
// canvas.drawPoint(100.0f, 100.0f, p);
canvas.drawLine(0, 110, 500, 110, p);
}

// 绘制surface2 其中使用线程
surfaceDraw = (SVDraw) findViewById(R.id.mDraw);
surfaceDraw.setVisibility(View.VISIBLE);
surfaceDraw.drawLine();
}

// =============================create surface 1=================================================
private class MySurfaceViewCallback implements SurfaceHolder.Callback {
@Override
public void surfaceChanged(SurfaceHolder holder, int format, int width,
int height) {
}

@SuppressWarnings("deprecation")
@Override
public void surfaceCreated(SurfaceHolder holder) {
cam = Camera.open(); // 取得第一个摄像头
Parameters param = cam.getParameters();
// param.setPreviewSize(display.getWidth(), display.getHeight()) ;
param.setPreviewFrameRate(5); // 一秒5帧
param.setPictureFormat(PixelFormat.JPEG); // 图片形式
param.set("jpen-quality", 80);
cam.setParameters(param);
cam.setDisplayOrientation(90); // 纠正摄像头自动旋转,纠正角度,如果引用,则摄像角度偏差90度

try {
cam.setPreviewDisplay(holder);
} catch (IOException e) {
}

cam.startPreview(); // 进行预览
previewRunning = true; // 已经开始预览
}

@Override
public void surfaceDestroyed(SurfaceHolder holder) {
if (cam != null) {
if (previewRunning) {
cam.stopPreview(); // 停止预览
previewRunning = false;
}
cam.release();
}
}
}
}

/*只不过一个是继承的view一个是surfaceview,将AttributeSetattrs加上。只要处理好谁是顶层的view谁设成透明,预览视频的surfaceview设成底层,在且要在xml属性文件里设成visible就可以了*/
public class SVDraw extends SurfaceView implements SurfaceHolder.Callback{

protected SurfaceHolder sh;
private int mWidth;
private int mHeight;
private MyThread thread;

public SVDraw(Context context, AttributeSet attrs) {
super(context, attrs);
sh = this.getHolder();
sh.addCallback(this);
sh.setFormat(PixelFormat.TRANSPARENT);
setZOrderOnTop(true);
}

public void surfaceChanged(SurfaceHolder arg0, int arg1, int w, int h) {
mWidth = w;
mHeight = h;
}

public void surfaceCreated(SurfaceHolder arg0) {

}

public void surfaceDestroyed(SurfaceHolder arg0) {

}
void clearDraw()
{
Canvas canvas = sh.lockCanvas();
canvas.drawColor(Color.BLUE);
sh.unlockCanvasAndPost(canvas);
}
public void drawLine()
{
//预览视频的时候绘制图像
/*Canvas canvas = sh.lockCanvas();
canvas.drawColor(Color.TRANSPARENT);
Paint p = new Paint();
p.setAntiAlias(true);
p.setColor(Color.RED);
p.setStyle(Style.STROKE);
//canvas.drawPoint(100.0f, 100.0f, p);
canvas.drawLine(0,110, 500, 110, p);
canvas.drawCircle(110, 110, 10.0f, p);
sh.unlockCanvasAndPost(canvas);*/

thread = new MyThread(sh);
thread.setRun(true);
thread.start();
}
}

// 绘制线程
public class MyThread extends Thread {
private SurfaceHolder holder;
private boolean run;

public MyThread(SurfaceHolder holder) {
this.holder = holder;
run = true;
}

@Override
public void run() {
int counter = 0;
Canvas canvas = null;
while (run) {
// 具体绘制工作
try {
// 获取Canvas对象,并锁定之
canvas = holder.lockCanvas();
// 设定Canvas对象的背景颜色
canvas.drawColor(Color.TRANSPARENT);

// 创建画笔
Paint p = new Paint();
// 设置画笔颜色
p.setColor(Color.RED);
// 设置文字大小
p.setTextSize(30);

// 创建一个Rect对象rect
Rect rect = new Rect(100, 50, 380, 330);
// 在canvas上绘制rect
canvas.drawRect(rect, p);
// 在canvas上显示时间
canvas.drawText("Interval = " + (counter++) + " seconds.", 100, 410, p);
Thread.sleep(1000);
} catch (Exception e) {
e.printStackTrace();
} finally {
if (canvas != null) {
// 解除锁定,并提交修改内容
holder.unlockCanvasAndPost(canvas);
}
}
}
}

public boolean isRun() {
return run;
}

public void setRun(boolean run) {
this.run = run;
}
}

<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.example.test02"
android:versionCode="1"
android:versionName="1.0" >

<uses-sdk
android:minSdkVersion="8"
android:targetSdkVersion="18" />

<application
android:allowBackup="true"
android:icon="@drawable/ic_launcher"
android:label="@string/app_name"
android:theme="@style/AppTheme" >
<activity
android:name="com.example.test02.MainActivity"
android:label="@string/app_name" >
<intent-filter>
<action android:name="android.intent.action.MAIN" />

<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
</application>

<!--z>
&nbsp;<uses-feature android:name="android.hardware.camera" />
<uses-feature android:name="android.hardware.camera.autofocus" />
<uses-permission android:name="android.permission.CAMERA" />
<uses-permission android:name="android.permission.MOUNT_UNMOUNT_FILESYSTEMS" />
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
</manifest>

android 使用两个surfaceview 在摄像机画面上绘图的更多相关文章

  1. android 加载自定义图片并在图片上绘图

    来源:毕设 关键词:Bitmap Canvas //毕设中需要自定义室内地图,并且在地图上绘制轨迹 //此处是一个测试Demo,实现图片的加载和记录手指在屏幕上的运动轨迹 图片的载入 使用系统提供的内 ...

  2. Android之View和SurfaceView

    Android之View和SurfaceView Android游戏当中主要的除了控制类外就是显示类View.SurfaceView是从View基类中派生出来的显示类.android游戏开发中常用的三 ...

  3. Android 学习笔记之SurfaceView的使用+如何实现视频播放...

    学习内容: 1.掌握Surface的使用... 2.Android中如何实现视频播放... 1.SurfaceView类的使用   在Android中,一般播放音频时我们可以去使用Android提供的 ...

  4. Unity调用Android的两个方式:其一、调用jar包

    unity在Android端开发的时候,免不了要调用Java:Unity可以通过两种方式来调用Android:一是调用jar.二是调用aar. 这篇文章主要讲解怎么从无到有的生成一个jar包,然后un ...

  5. Android 实现两屏幕互相滑动

    Android 实现两屏幕互相滑动 下文来自: http://blog.csdn.net/song_shi_chao/article/details/7081664 ----------------- ...

  6. 【转】Android Fragment中使用SurfaceView切换时闪一下黑屏的解决办法

    重构了下之前自己的一个新闻客户端,全部使用了Fragment来进行页面切换,只有一个入口Activity作为程序的启动Activity,其中有一个界面需要调用摄像头识别二维码, 于是就会用到Surfa ...

  7. unity调用Android的两种方式:其二,调用aar包

    上一篇我们讲了unity如何调用jar包 http://www.cnblogs.com/Jason-c/p/6743224.html, 现在我们介绍一下怎么生成aar包和unity怎么调用aar 一. ...

  8. Unity调用Android的两种方式:其一、调用jar包

    unity在Android端开发的时候,免不了要调用Java:Unity可以通过两种方式来调用Android:一是调用jar.二是调用aar. 这篇文章主要讲解怎么从无到有的生成一个jar包,然后un ...

  9. android多线程-AsyncTask之工作原理深入解析(上)

    关联文章: Android 多线程之HandlerThread 完全详解 Android 多线程之IntentService 完全详解 android多线程-AsyncTask之工作原理深入解析(上) ...

随机推荐

  1. 【三支火把】---CDS5516舵机调试以及自己的感想!

    我依然坚持,任何一次自己的心有感触都要及时的记录下来,这样你的努力才是真正的努力. 这两天一直在用STM32调试CDS5516舵机,其实很简单,但是却花了将近两天的时间,过程之曲折我就不说了,先总结一 ...

  2. 【Java】Socket+多线程实现控制台聊天室

    转载请注明原文地址:http://www.cnblogs.com/ygj0930/p/5827212.html 聊天室程序的结构图: 架构解释: Server服务器相当于一个中转站,Client客户端 ...

  3. 三、FreeMarker 模版开发指南 第三章 模版

    章节内容如下:   总体结构 指令 表达式 插值 一.总体结构 实际上你用程序语言编写的程序就是模板,模板也被称为FTL(代表FreeMarker模板语言).这是为编写模板设计的非常简单的编程语言. ...

  4. php and web service with wsdl

    Following are the links: Developing Web Services Using PHP PHP Web Services with WSDL Creating Web S ...

  5. Windows 窗体的.Net 框架绘图技术

    当编写一个典型的Windows 窗体程序时,窗体和控件的绘制.效果等操作是不需要特别加以考虑的.这是为什么呢?因为通过使用 .Net 框架,开发人员可以拖动一系列的控件到窗体上,并书写一些简单的与事件 ...

  6. decide your linux OS is GUI or not

    Try:  ps -ef|grep X  The ps command will display information about a selection of the active process ...

  7. Ubuntu下多服务器 Rsync同步镜像服务配置

    主服务器:192.168.5.13_ubuntu 从服务器:192.168.5.11_centos ================== 1> 在两台主机上分别安装rsync========== ...

  8. 不会内存溢出的Android Handler写法

    private static class ThisHandler extends Handler {     private final WeakReference<MainActivity&g ...

  9. C#并行编程 (Barrier,CountdownEvent,ManualResetEventSlim,SemaphoreSlim,SpinLock,SpinWait )

    背景 有时候必须访问变量.实例.方法.属性或者结构体,而这些并没有准备好用于并发访问,或者有时候需要执行部分代码,而这些代码必须单独运行,这是不得不通过将任务分解的方式让它们独立运行. 当任务和线程要 ...

  10. QNetworkAccessManager的异步与线程

    Qt版本5.1.1 以HTTP操作为例 Qt中的HTTP操作都是异步的. 内部通过线程实现 创建线程的时机在QNetworkReplyHttpImplPrivate::postRequest() vo ...