当前位置: 首页 > news >正文

网站开发公司排名前十南京外贸推广

网站开发公司排名前十,南京外贸推广,沈阳创新网站建设报价,wordpress技术博客主题1. 前言 这段时间#xff0c;在使用 natario1/CameraView 来实现带滤镜的预览、拍照、录像功能。 由于CameraView封装的比较到位#xff0c;在项目前期#xff0c;的确为我们节省了不少时间。 但随着项目持续深入#xff0c;对于CameraView的使用进入深水区#xff0c;逐…1. 前言 这段时间在使用 natario1/CameraView 来实现带滤镜的预览、拍照、录像功能。 由于CameraView封装的比较到位在项目前期的确为我们节省了不少时间。 但随着项目持续深入对于CameraView的使用进入深水区逐渐出现满足不了我们需求的情况。 Github中的issues中有些BUG作者一直没有修复。 那要怎么办呢 ? 项目迫切地需要实现相关功能只能自己硬着头皮去看它的源码去解决这些问题。 上篇文章我们对带滤镜拍照的相关类有了大致的了解这篇文章我们来看下CameraView是怎么实现带滤镜预览的。 以下源码解析基于CameraView 2.7.2 implementation(com.otaliastudios:cameraview:2.7.2)为了在博客上更好的展示本文贴出的代码进行了部分精简 2. 初始化CameraEngine 这部分逻辑和普通的预览一样 : Android 相机库CameraView源码解析 (一) : 预览 这里就略过了。 protected CameraEngine instantiateCameraEngine(Engine engine, CameraEngine.Callback callback) {if (mExperimental engine Engine.CAMERA2) {return new Camera2Engine(callback);} else {mEngine Engine.CAMERA1;return new Camera1Engine(callback);} }3. 初始化CameraPreview 这里和不同预览不同的地方是普通的预览创建的是SurfaceCameraPreview而使用OpenGL的预览使用的是GlCameraPreview protected CameraPreview instantiatePreview(NonNull Preview preview,NonNull Context context,NonNull ViewGroup container) {switch (preview) {case SURFACE:return new SurfaceCameraPreview(context, container);case TEXTURE: {if (isHardwareAccelerated()) {// TextureView is not supported without hardware acceleration.return new TextureCameraPreview(context, container);}}case GL_SURFACE:default: {mPreview Preview.GL_SURFACE;return new GlCameraPreview(context, container);}} }4. 初始化GLSurfaceView 在GlCameraPreview的onCreateView()方法中初始化了GLSurfaceView 4.1 初始化布局 在初始化布局中通过findViewById获得了GLSurfaceView protected GLSurfaceView onCreateView(NonNull Context context, NonNull ViewGroup parent) {ViewGroup root (ViewGroup) LayoutInflater.from(context).inflate(R.layout.cameraview_gl_view, parent, false);final GLSurfaceView glView root.findViewById(R.id.gl_surface_view);//...省略了代码...在下文中详细说明parent.addView(root, 0);mRootView root;return glView; }4.2 初始化Renderer 这里创建了Renderer类Renderer是我们这里的关键下文会详细再讲 final Renderer renderer instantiateRenderer();protected Renderer instantiateRenderer() {return new Renderer(); }4.3 将GlCameraPreview和Renderer建立关联 这里调用了glView.setRenderer将GlCameraPreview和Renderer建立了关联 glView.setEGLContextClientVersion(2); glView.setRenderer(renderer); glView.setRenderMode(GLSurfaceView.RENDERMODE_WHEN_DIRTY);5. Renderer类 Renderer类继承自GLSurfaceView.Renderer有3个实现方法onSurfaceCreated、onSurfaceChanged、onDrawFrame public interface Renderer {void onSurfaceCreated(GL10 gl, EGLConfig config);void onSurfaceChanged(GL10 gl, int width, int height);void onDrawFrame(GL10 gl); }5.1 onSurfaceCreated 在onSurfaceCreated里我们会初始化GlTextureDrawer并将Filter赋值给GlTextureDrawerGlTextureDrawer是负责绘制的类。 接着由于我们使用的是GLSurfaceView.RENDERMODE_WHEN_DIRTY所以要在合适的时机去调用requestRender来通知OpenGL渲染。 public void onSurfaceCreated(GL10 gl, EGLConfig config) {if (mCurrentFilter null) {mCurrentFilter new NoFilter();}mOutputTextureDrawer new GlTextureDrawer();mOutputTextureDrawer.setFilter(mCurrentFilter);final int textureId mOutputTextureDrawer.getTexture().getId();mInputSurfaceTexture new SurfaceTexture(textureId);getView().queueEvent(new Runnable() {Overridepublic void run() {for (RendererFrameCallback callback : mRendererFrameCallbacks) {callback.onRendererTextureCreated(textureId);}}});// Since we are using GLSurfaceView.RENDERMODE_WHEN_DIRTY, we must notify// the SurfaceView of dirtyness, so that it draws again. This is how its done.mInputSurfaceTexture.setOnFrameAvailableListener(new SurfaceTexture.OnFrameAvailableListener() {Overridepublic void onFrameAvailable(SurfaceTexture surfaceTexture) {getView().requestRender(); // requestRender is thread-safe.}}); }还有一点会分发RendererFrameCallback回调的onRendererTextureCreated()带滤镜拍照、录像都实现了RendererFrameCallback回调从而来现实拍照和录像的功能。 SnapshotGlPictureRecorder中take()的时候会添加该回调 : 是用来拍照的。SnapshotVideoRecorder : 是用来录制视频的。 这两个我们后面的文章会讲这里先略过。 5.2 onSurfaceChanged 5.2.1 设置尺寸 在onSurfaceChanged方法中会调用gl.glViewport从而确定OpenGL窗口中显示的区域。 然后会调用Filter.setSize()从而设置滤镜的尺寸。 public void onSurfaceChanged(GL10 gl, final int width, final int height) {gl.glViewport(0, 0, width, height);mCurrentFilter.setSize(width, height);if (!mDispatched) {dispatchOnSurfaceAvailable(width, height);mDispatched true;} else if (width ! mOutputSurfaceWidth || height ! mOutputSurfaceHeight) {dispatchOnSurfaceSizeChanged(width, height);} }5.2.2 裁剪缩放计算 在dispatchOnSurfaceAvailable()中会将宽高赋值给mOutputSurfaceWidth和mOutputSurfaceHeight protected final void dispatchOnSurfaceAvailable(int width, int height) {mOutputSurfaceWidth width;mOutputSurfaceHeight height;if (mOutputSurfaceWidth 0 mOutputSurfaceHeight 0) {crop(mCropCallback);}if (mSurfaceCallback ! null) {mSurfaceCallback.onSurfaceAvailable();} }并调用crop进行裁剪缩放的计算这里的mCropping、mCropScaleX、mCropScaleY 都会在后面绘制的时候用到。 protected void crop(Nullable final CropCallback callback) {if (mInputStreamWidth 0 mInputStreamHeight 0 mOutputSurfaceWidth 0 mOutputSurfaceHeight 0) {float scaleX 1f, scaleY 1f;AspectRatio current AspectRatio.of(mOutputSurfaceWidth, mOutputSurfaceHeight);AspectRatio target AspectRatio.of(mInputStreamWidth, mInputStreamHeight);if (current.toFloat() target.toFloat()) {// We are too short. Must increase height.scaleY current.toFloat() / target.toFloat();} else {// We must increase width.scaleX target.toFloat() / current.toFloat();}mCropping scaleX 1.02f || scaleY 1.02f;mCropScaleX 1F / scaleX;mCropScaleY 1F / scaleY;getView().requestRender();}if (callback ! null) callback.onCrop(); }5.3 onDrawFrame 在我们调用requestRender()后就会触发onDrawFrame。 在onDrawFrame中会操作OpenGL进行重新的绘制并渲染到GlSurfaceView上从而达到预览的效果。 5.3.1 进行裁剪、旋转等操作 这部分获取了transform 矩阵然后根据之前计算出来的mCropping、mCropScaleX、mCropScaleY 等参数进行裁剪和旋转的操作 final float[] transform mOutputTextureDrawer.getTextureTransform(); mInputSurfaceTexture.updateTexImage(); mInputSurfaceTexture.getTransformMatrix(transform); // LOG.v(onDrawFrame:, timestamp:, mInputSurfaceTexture.getTimestamp());// For Camera2, apply the draw rotation. // See TextureCameraPreview.setDrawRotation() for info. if (mDrawRotation ! 0) {Matrix.translateM(transform, 0, 0.5F, 0.5F, 0);Matrix.rotateM(transform, 0, mDrawRotation, 0, 0, 1);Matrix.translateM(transform, 0, -0.5F, -0.5F, 0); }if (isCropping()) {// Scaling is easy, but we must also translate before:// If the view is 10x1000 (very tall), it will show only the left strip// of the preview (not the center one).// If the view is 1000x10 (very large), it will show only the bottom strip// of the preview (not the center one).float translX (1F - mCropScaleX) / 2F;float translY (1F - mCropScaleY) / 2F;Matrix.translateM(transform, 0, translX, translY, 0);Matrix.scaleM(transform, 0, mCropScaleX, mCropScaleY, 1); }5.3.2 进行绘制 接着调用mOutputTextureDrawer.draw()从而重新进行绘制并渲染到GlSurfaceView上从而达到了预览的效果。 mOutputTextureDrawer.draw(mInputSurfaceTexture.getTimestamp() / 1000L);5.3.3 分发回调 最后会调用RendererFrameCallback.onRendererFrameRendererFrameCallback我们刚才已经说过了带滤镜拍照、录像都实现了这个RendererFrameCallback回调从而来现实拍照和录像的功能这不是本文的重点这里我们也先略过后续文章中会详细讲解。 for (RendererFrameCallback callback : mRendererFrameCallbacks) {callback.onRendererFrame(mInputSurfaceTexture, mDrawRotation, mCropScaleX, mCropScaleY); }6. 其他 6.1 CameraView源码解析系列 Android 相机库CameraView源码解析 (一) : 预览-CSDN博客 Android 相机库CameraView源码解析 (二) : 拍照-CSDN博客 Android 相机库CameraView源码解析 (三) : 滤镜相关类说明-CSDN博客 Android 相机库CameraView源码解析 (四) : 带滤镜预览-CSDN博客 Android 相机库CameraView源码解析 (五) : 带滤镜拍照-CSDN博客 Android 相机库CameraView源码解析 (六) : 保存滤镜效果-CSDN博客
http://www.dnsts.com.cn/news/215268.html

相关文章:

  • 佛山做网站优化兰州 电子 网站建设
  • 建网站业务员长春网站设计制作培训
  • 大学生简历制作网站免费移动网站模板下载安装
  • 平湖公司做网站旅游网站建设的市场分析
  • 经销商城建站典型的网络营销案例
  • asp.net视频网站模板下载wordpress数据库在哪
  • 高端营销型企业网站建设梧州红豆论坛
  • 网站基本框架一个网站怎么做软件
  • 网站找建站公司wordpress表单模板
  • 北京南站官网wordpress link
  • 哈尔滨网站建设推广服务如何组建一个小型局域网
  • 一个虚拟主机可以做几个网站手机网站自助建
  • 网站群 意义关于开展网站建设工作的通知
  • 做网站注册有哪些怎么做360网站排名
  • shopex进入网站自动回跳转到别的网站 是否被挂马德语网站制作
  • APP开发网站建设哪家好淘宝自动推广软件
  • 中国网站建设调查分析长沙网站建设及推广公司
  • 重庆网站搜索引擎seowordpress多语言包
  • 个人建设视频网站网站建设任务书
  • 新手搭建网站网站设计规划的创意
  • 网站设计需求原型图焦作网站建设服务
  • 河南网站建设途径有什么网页设计软件免费版
  • 陇南市建设局网站友情链接出售
  • win7做网站做家具的网站
  • 做网站关键词优化的公司网站产品图片尺寸
  • 网站seo站外优化福州 网站设计公司
  • 重庆建新建设工程有限公司网站怎么用代码创建网站教程
  • rss网站推广法中国建筑设计行业网
  • 专门做钻石国外网站青岛网站建设信息公示
  • dedecms做网站注意事项给网站做导流