首页 » 网站建设 » grafikaphp圆角技巧_鸿蒙开源全场景应用开拓通讯协议

grafikaphp圆角技巧_鸿蒙开源全场景应用开拓通讯协议

访客 2024-11-25 0

扫一扫用手机浏览

文章目录 [+]

图1 家庭合影美颜相机运用运行效果图

2.RTP传输Demo效果

为了更清晰地讲解通讯协议,我们将家庭合影美颜相机运用中数据传输部分拆分出来,形成了一个RTP传输Demo,并进行了功能整理和优化,将原来的视频传输改为了图像传输,视频是由多帧图像构成,传输数据类型的改变不会影响RTP传输事理和步骤。
RTP传输Demo的运行效果图如图2所示,左图为发送端效果,右图为吸收端效果。
成功安装并打开运用后,在发送端点击蓝色按钮,发送开拓者选中的特定区域的图片数据;在吸收端点击粉色按钮,吸收发送端刚发送的图片数据,并在按钮下方显示。

grafikaphp圆角技巧_鸿蒙开源全场景应用开拓通讯协议

图2 RTP传输Demo运行效果图(左发送端,右吸收端)

grafikaphp圆角技巧_鸿蒙开源全场景应用开拓通讯协议
(图片来自网络侵删)
RTP传输事理及步骤解析

接下来为大家重点解析RTP传输的实现事理和步骤。
RTP传输Demo的事理流程可参考图3。
在鸿蒙发送端(做事端),设置须要传输的图像数据,通过无线网络,利用RTP协议和Socket点对点的数据通信办法,发送到鸿蒙吸收端(客户端)。
在鸿蒙吸收端(客户端),吸收到发送端发来的图像数据后,进行图像绘制。
接下来将针对RTP传输Demo的实现步骤进行解析。

图3 RTP传输事理流程图

做事端数据发送

在做事端,将待发送的图像置于resources->base->media文件夹下,如图4所示。
然后对待发送的图像数据进行格式转换。
通过无线网络,利用RTP协议和Socket点对点的数据通信办法,将图像数据传输至鸿蒙吸收端。

图4 图片在项目构造中的位置

做事真个数据发送流程包含以下三个步骤:步骤1. 通过资源ID获取位图工具;步骤2. 将位图指定区域像素进行格式转换;步骤3. 数据传输;(1)通过资源ID获取位图工具通过getResource()方法,以资源IDdrawableID工具作为入参,获取资源输入流drawableInputStream;实例化图像设置类ImageSource.SourceOptions工具,并设置图像源格式为png;创建图像源,参数为资源输入流和图像源ImageSource类工具;实例化图像参数类DecodingOptions的工具,为其初始化图像尺寸、区域并设置位图格式;根据像参数类工具decodingOptions,通过图像源ImageSource类工具创建位图工具;返回位图工具。

//通过资源ID获取位图工具private PixelMap getPixelMap(int drawableId) { InputStream drawableInputStream = null; try { //以资源ID作为入参,获取资源输入流 drawableInputStream=this.getResourceManager().getResource(drawableId); //实例化图像源ImageSource类工具 ImageSource.SourceOptions sourceOptions = new ImageSource.SourceOptions(); sourceOptions.formatHint = "image/png";//设置图像源格式 //创建图像源,参数为资源输入流和图像源ImageSource类工具 ImageSource imageSource = ImageSource.create(drawableInputStream, sourceOptions); //实例化图像源解码操作DecodingOptions类工具 ImageSource.DecodingOptions decodingOptions = new ImageSource.DecodingOptions(); decodingOptions.desiredSize = new Size(0, 0);//设置图像尺寸 decodingOptions.desiredRegion = new Rect(0, 0, 0, 0); decodingOptions.desiredPixelFormat = PixelFormat.ARGB_8888;//设置位图格式 PixelMap pixelMap = imageSource.createPixelmap(decodingOptions);//根据解码操作类工具,创建位图 return pixelMap;//返回位图 } ...}

(2)将位图指定区域像素进行格式转换在得到位图工具后,实例化矩形Rect矩形类工具,用于为开拓者选中特定的图像区域(该区域应不大于resources->base->media路径下图像的大小);通过位图工具pixelMap调用readPixels()方法将指定区域像素转换为int[]类型数据;调用intToBytes()方法再将int[]类型数据格式转换为byte类型数据。

// 读取指定区域像素Rect region = new Rect(0, 0, 30, 30);//实例化举行类工具,规定指定区域pixelMap.readPixels(pixelArray,0,30,region);//将指定区域像素转换为int[]类型数据pic = intToBytes(pixelArray);//将int[]类型数据昂虎子你换位byte类型数据

(3)数据传输实例化RTP发送类工具RtpSenderWrapper,将IP地址设置为吸收端手机IP地址,端口号设置为5005;调用sendAvcPacket()方法发送图像数据。
由于对RTP传输的数据类型做了简化,因此图像RTP传输会相对随意马虎,而如果是原运用中的视频RTP传输,则须要逐帧对视频数据进行格式转换,并将从摄像头获取的YUV类型的原始视频数据压缩为h264类型的视频数据,以方便Socket进行传输。

mRtpSenderWrapper = new RtpSenderWrapper("192.168.31.12", 5005, false);mRtpSenderWrapper.sendAvcPacket(pic, 0, pic.length, 0);//发送数据客户端吸收数据

在发送端通过RTP协议成功发送数据后,吸收端就可以正常开始吸收了。
发送端吸收数据的流程紧张分为以下5个步骤:步骤1. 创建数据吸收线程;步骤2. 吸收数据;步骤3. 在线程间进行数据通报;步骤4. 处理位图数据得到pixelMapHolder;步骤5. 绘制图像。
(1)创建数据吸收线程创建子线程作为数据吸收线程。

new Thread(new Runnable())//新开一个数据吸收线程

(2)吸收数据在子线程吸收线程中,实例化数据包DatagramPacket;通过Socket类工具调用receive()方法,吸收发送真个数据到数据包DatagramPacket中;通过数据包DatagramPacket调用getData()方法获取数据包中的RTP数据。

datagramPacket = new DatagramPacket(data,data.length);//实例化数据包socket.receive(datagramPacket);//吸收数据到数据包中rtpData = datagramPacket.getData();获取数据包中的RTP数据

(3)在线程间进行数据通报待子线程拿到RTP发送数据后,须要将RTP数据从子线程通报到主线程。
这就涉及到线程间的数据通报。
在此运用中,我们利用了Java类的SynchronousQueue并发行列步队来实现子线程和主线程间的数据通报。
先实例化一个byte[]类型的并发行列步队SynchronousQueue类工具;将h264类型的数据放入并发行列步队中;再从行列步队中获取数据。

SynchronousQueue<byte[]> queue = new SynchronousQueue<byte[]>();//实例化byte[]类型的并发行列步队queue.put(h264Data);//将h264类型的数据放入并发行列步队中rgbData = queue.take();//从行列步队中获取数据

(4)处理解码后的位图数据得到PixelMapHolder主线程从行列步队中拿到图像RGB数据后即可进行图像绘制。
PixelMap是吸劳绩得的位图数据,PixelMapHolder 利用 PixelMap 天生渲染后端所需的数据,并供应数据作为 Canvas 中方法的输入参数。
因此为了后续能够对位图进行渲染,须要在图像数据从子线程通报到主线程后,将图像数据pixelmap转换为pixelMapHolder类工具,即在实例化pixelMapHolder类工具时,将pixelmap位图数据作为入参传入实例化方法中。

public void putPixelMap(PixelMap pixelMap){ if (pixelMap != null) {//判断吸收到的位图数据是否为空 rectSrc = new RectFloat(0, 0, pixelMap.getImageInfo().size.width, pixelMap.getImageInfo().size.height); pixelMapHolder = new PixelMapHolder(pixelMap);//实例化PixelMapHolder类工具 }else{ pixelMapHolder = null;//若吸收到的位图为空,则全部置为空 setPixelMap(null); } }

(5)绘制图像实例化一个矩形Rect类工具,设置图像信息并规定指定的区域如宽和高;添加一个同步绘制任务,先判断pixelMapHolder是否为空,若为空则直接返回,不为空则开始绘制任务;在绘制任务中,调用drawPixelMapHolderRoundRectShape()方法将PixelMapHolder类工具绘制到实例化得到的矩形Rect类工具中,并设置其为圆角效果;其位置由rectDst指定;绘制完成后开释pixelMapHolder,将其置为空。

private void onDraw(){ this.addDrawTask((view, canvas) -> { //添加绘制任务 if (pixelMapHolder == null){//判断pixelMapHolder是否为空 return; } synchronized (pixelMapHolder) {//在同步任务中绘制图像 canvas.drawPixelMapHolderRoundRectShape(pixelMapHolder, rectSrc, rectDst, radius, radius);//绘制图像为圆角效果 pixelMapHolder = null;//绘制完成后将pixelMapHolder开释 } });}安卓端美颜滤镜效果实现

美颜滤镜的部分我们参考了GitHub上的开源项目(https://github.com/google/grafika、https://github.com/cats-oss/android-gpuimage、https://github.com/wuhaoyu1990/MagicCamera),利用GPU着色器实现添加滤镜和切换滤镜的效果。
由于不涉及鸿蒙的能力,此部分不作为重点讲述,只简要概括下实在现流程,可分为如下5个步骤:(1)设置不同的滤镜利用着色器措辞,设置所需的多种代码。

图5 美颜相机利用的滤镜

(2)opengl绘制;

import android.opengl.GLES20;...// add the vertex shader to programGLES20.glAttachShader(mProgram, vertexShader); // add the fragment shader to programGLES20.glAttachShader(mProgram, fragmentShader); // creates OpenGL ES program executablesGLES20.glLinkProgram(mProgram);

(3)添加滤镜;

private List<FilterFactory.FilterType>filters = new ArrayList<>(); ... filters.add(FilterFactory.FilterType.Original); filters.add(FilterFactory.FilterType.Sunrise); ...

(4)开启或关闭美颜滤镜;

mCameraView.enableBeauty(true);

(5)设置美颜程度;

mCameraView.setBeautyLevel(0.5f);

(6)设置切换滤镜和切换镜头,再设置相机拍摄和拍摄完成后的回调即可。

mCameraView.updateFilter(filters.get(pos));//切花滤镜mCameraView.switchCamera();//切换镜头项目贡献人

蔡志杰 李珂 朱伟 郑森文 陈美汝

标签:

相关文章

五维视角下的语言技能发展

语言是人类沟通的桥梁,是文明进步的象征。在全球化的大背景下,语言技能的重要性愈发凸显。本文将从听、说、读、写、译五个维度,探讨语言...

网站建设 2024-12-27 阅读0 评论0

二维码在当今社会的重要性与应用

随着科技的飞速发展,二维码已经成为了我们生活中不可或缺的一部分。作为一种信息存储、传递和识别的技术,二维码凭借其便携、高效、安全等...

网站建设 2024-12-27 阅读0 评论0

书籍中的智慧之光,探寻生命的奥秘

在浩瀚的书海中,每一本书都如同一座灯塔,照亮我们前行的道路。那些充满智慧的语言,犹如夜空中最亮的星,引领我们探索生命的奥秘。本文将...

网站建设 2024-12-27 阅读0 评论0