前言

在SurfaceView初步以及Camera初步中我介绍了如何使用SurfaceView以及如何使用SurfaceView来预览Camera画面,接下来我就来介绍下如何给Camera添加水印效果。由于SurfaceView不支持回显,也就是将摄像头捕获到的数据处理以后重新设置到界面上,所以我会使用两个SurfaceView来介绍。

思路

我们想给预览界面添加水印第一步肯定是需要获取到每一帧的数据然后处理完以后再绘制到界面上,Android为Camera提供了两个接口用于获取每一帧的数据。分别如下

1

2

3

4

5

6

//每一帧准备好了就直接回调

voidandroid.hardware.Camera.setPreviewCallback(PreviewCallbackcb)

//带有缓存的回调,调用

//void android.hardware.Camera.addCallbackBuffer(byte[] callbackBuffer)

//方法才会回调,每调用一次回调一次

voidandroid.hardware.Camera.setPreviewCallbackWithBuffer(PreviewCallbackcb)

第一种方式:setPreviewCallback方法,设置回调接口:PreviewCallback

在回调方法:onPreviewFrame(byte[] data, Camera camera) 中处理每一帧数据

第二种方式:setPreviewCallbackWithBuffer方法,同样设置回调接口:PreviewCallback,不过还需要一个方法配合使用:addCallbackBuffer,这个方法接受一个byte数组。

第二种方式和第一种方式唯一的区别:

第一种方式是onPreviewFrame回调方法会在每一帧数据准备好了就调用,但是第二种方式是在需要在前一帧的onPreviewFrame方法中调用addCallbackBuffer方法,下一帧的onPreviewFrame才会调用,同时addCallbackBuffer方法的参数的byte数据就是每一帧的原数据。所以这么一看就好理解了,就是第一种方法的onPreviewFrame调用是不可控制的,就是每一帧数据准备好了就回调,但是第二种方法是可控的,我们通过addCallbackBuffer的调用来控制onPreviewFrame的回调机制。

注意:

因为第二种方式在调用的时候有点注意的地方:

1、在调用Camera.startPreview()接口前,我们需要setPreviewCallbackWithBuffer,而setPreviewCallbackWithBuffer之前我们需要重新addCallbackBuffer,因为setPreviewCallbackWithBuffer 使用时需要指定一个字节数组作为缓冲区,用于预览图像数据 即addCallbackBuffer,然后你在onPerviewFrame中的data才会有值。

2、从上面看来,我们设置addCallbackBuffer的地方有两个,一个是在startPreview之前,一个是在onPreviewFrame中,这两个都需要调用,如果在onPreviewFrame中不调用,那么,就无法继续回调到onPreviewFrame中了。

编码

当我们设置好回调接口以后就可以在里面获取到数据了,不过这里的数据默认为NV21格式,所以我们需要转换为图像才行。

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

@Override

publicvoidonPreviewFrame(byte[]data,Cameracamera){

Sizesize=camera.getParameters().getPreviewSize();

if(mCustomSurfaceView==null){

return;

}

// 将NV21类型的数据转为Image

YuvImageyuvImage=newYuvImage(data,ImageFormat.NV21,size.width,size.height,null);

if(yuvImage!=null){

initPaint();

ByteArrayOutputStreamout=newByteArrayOutputStream();

yuvImage.compressToJpeg(newRect(0,0,size.width,size.height),80,out);

// 得到原始图片

Bitmapbitmap=BitmapFactory.decodeByteArray(out.toByteArray(),0,out.size());

SurfaceHoldercustomSurfaceHolder=mCustomSurfaceView.getHolder();

// 获取到画布

Canvascanvas=customSurfaceHolder.lockCanvas();

// 将加了水印的图片绘制到预览窗口

canvas.drawBitmap(BitmapUtil.rotateBitmapAndWaterMark(bitmap,90,"www.27house.cn",paint),0,0,null);

customSurfaceHolder.unlockCanvasAndPost(canvas);

}

}

上面的代码中,我首先将NV21类型的数据转为Image,然后获取预览SurfaceView的Canvas,然后将处理的结果绘制上去即可。关于图片的旋转以及添加水印,可以参考Android绘图基本操作。http://27house.cn/archives/405

图片处理操作如下,主要是将图片旋转了90°,关于旋转的原因请查看上篇博客Camera初步,然后绘制水印以及时间戳。

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

28

29

30

31

/**

* 给图片添加水印和时间戳

*

* @param originBitmap 原始图片

* @param degree 旋转角度

* @param watermark 水印文字

* @param paint 绘制水印的画笔对象

* @return 最终处理的结果

*/

publicstaticBitmaprotateBitmapAndWaterMark(BitmaporiginBitmap,intdegree,Stringwatermark,Paintpaint){

intwidth=originBitmap.getWidth();

intheight=originBitmap.getHeight();

BitmapresultBitmap=Bitmap.createBitmap(width,height,Bitmap.Config.ARGB_8888);

Canvascanvas=newCanvas(resultBitmap);

canvas.save();

canvas.rotate(degree,width/2,height/2);

canvas.drawBitmap(originBitmap,0,0,null);

canvas.restore();

inttextWidht=(int)paint.measureText(watermark);

FontMetricsfontMetrics=paint.getFontMetrics();

inttextHeight=(int)(fontMetrics.ascent-fontMetrics.descent);

intx=(width-textWidht)/2;

inty=(height-textHeight)/2;

y=(int)(y-fontMetrics.descent);

canvas.drawText(watermark,x,y,paint);

canvas.drawText(String.valueOf(System.currentTimeMillis()),x,y+textHeight,paint);

// 立即回收无用内存

originBitmap.recycle();

originBitmap=null;

returnresultBitmap;

}

android yuv加水印_Android Camera添加预览水印相关推荐

  1. Android开发实践:掌握Camera的预览方向和拍照方向

    Android的Camera相关应用开发中,有一个必须搞清楚的知识点,就是Camera的预览方向和拍照方向,本文就重点讨论一下这个问题. 图像的Sensor方向:手机Camera的图像数据都是来自于摄 ...

  2. Android 实现相机(Camera)预览

    CameraX 是一个 Jetpack 库,旨在帮助您更轻松地开发相机应用. 对于新应用,我们建议从 CameraX 开始.它提供一致且易于使用的 API,适用于绝大多数 Android 设备,并向后 ...

  3. el-image做水印,给image预览图片添加图标

    实现效果:可以做水印,可以给预览图添加预览图标 实现:在鼠标hover时添加一个类名即可. <el-image style="width: 124px;":src=" ...

  4. Android屏幕计算正方形,Android Camera 正方形预览(二)

    一.概述 为实现Camera正方形预览,本Demo使用GLSurfaceView显示Camera预览数据,本文也主要针对GLSurfaceView的使用做介绍. Android中的视图有View.Su ...

  5. Android编程中调用Camera时预览画面有旋转问题的解决方法

    本文实例讲述了Android编程中调用Camera时预览画面有旋转问题的解决方法.分享给大家供大家参考,具体如下: 在调用Camera写应用的时候,前后摄像头的情况有时候是不一样的.有时候,明明后摄像 ...

  6. Android 音视频开发(三) -- Camera2 实现预览、拍照功能

    音视频 系列文章 Android 音视频开发(一) – 使用AudioRecord 录制PCM(录音):AudioTrack播放音频 Android 音视频开发(二) – Camera1 实现预览.拍 ...

  7. Android 8.0学习 (36)---Android 8.0 WebView 拍照、简易预览、二维码扫描 各种问题解决

    Android 8.0 WebView 拍照.简易预览.二维码扫描 各种问题解决 项目用到了WebView包装HTML5做成app使用,其中有页面用到了二维码和拍照上传功能.本人从未做过android ...

  8. Android 短视频编辑开发之摄像头预览实时美颜(三)

    前言: 在上一篇文章中给小伙伴们介绍了进行Camera预览,如果你还没有看过的话,建议先去看上一篇文章<Android 短视频开发之摄像头预览(二> 本篇文章会介绍如何实现摄像头预览画面实 ...

  9. Android 9.0 三方app whatsapp 拍照预览模糊

    之前在进行项目开发时,有碰到 Android 9.0 三方app whatsapp 拍照预览分辨率过低 现象,但是拍照出来的照片是清晰的, 查看log发现priview-size过低导致预览模糊,而p ...

最新文章

  1. POJ 3276 枚举+差分?
  2. ubuntu 网卡相关
  3. 国产奶粉冲击高端,飞鹤、蒙牛、合生元们的牌好不好打?
  4. springboot 之 webscoket 服务端推送
  5. jdk8读取文件_JDK 7和JDK 8中大行读取速度较慢的原因
  6. java dos窗口小工具下载,maxdos 9 3-maxdos工具箱 v9.3 官方版
  7. tqdm使用(Python进度条)
  8. ES6-Set集合的创建
  9. [转]分布式中Redis实现Session终结篇
  10. python列表属于什么类型的游戏_1.4 python数据类型之list类
  11. 大数据数据科学家常用面试题_面试有关数据科学,数据理解和准备的问答
  12. fiddler抓包工具1
  13. python中不同类型的数据不能相互运算_python语法入门(数据类型、运算)
  14. JavaWeb的目录结构(1)
  15. 暴走恭亲王:Jed McCaleb才是中本聪大魔王?
  16. java web后台开发跟手机APP后台开发有什么不同? 二者怎么通信?
  17. 关于Vmware workstation的软驱功能
  18. 计算机变量与变量地址,数据缓冲区与变量的地址(更新1)
  19. VOLATILE和队列
  20. 计算机组成与设计(硬件/软件接口)RISC-V版笔记

热门文章

  1. Unity3D Instantiate慢的问题
  2. java 判断一个字符串是否为纯数字
  3. salt-api https证书报错解决方法
  4. linux 创建临时文件目录 mktemp 命令 简介
  5. golang map 初始化 和 使用
  6. linux cron crontab anacron 计划任务 定时任务
  7. linux c 错误 'for' loop initial declaration used outside C99 mode
  8. linux系统调用(syscall)原理
  9. linux c 进程间通信
  10. qemu虚拟机与外部网络的通信