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

camera特效app(安卓)

文章目录

  • 1.前言:
  • 2. 效果预览:
  • 3.特效视频制作及上传
    • 3.1特效视频格式
    • 3.2视频上传到网站
    • 3.3 发布博客
  • 4.camera使用
  • 5.项目源码

1.前言:

相信大家都看过直播,直播中的礼物特效非常的炫酷,今天就教大家如何实现这一过程。其原理就是在摄像头画面上播放透明的特效视频。首先需要准备好mp4格式的特效视频。然后使用opengles进行渲染,实现透明化。当然,由于没有服务器,只能白嫖了。只需要把制作好的特效视频上传到好看视频网站上面,通过抓包拿到播放地址,然后将地址上传到一篇博客上面即可。启动app时首先会爬取该博客上面的视频播放地址。通过这种方法即可以减小app的体积(仅有3.5M),又无需自己购买服务器。后期如果需要更改或修改特效视频,只需要修改博客上面的播放地址即可。

2. 效果预览:

app下载地址:https://www.pgyer.com/T6he

3.特效视频制作及上传

3.1特效视频格式

特效视频的制作也很简单,视频格式如下所示:

在这里插入图片描述
视频的上半部分为我们想要的特效视频,下半部分为透明度,其值越接近255,则表示越不透明。在使用opengles渲染视频的时候,只需要把下半部分的像素值作为其透明度即可。

3.2视频上传到网站

关于视频如何上传到好看视频网站,已经如何抓包获取视频播放地址,我在之前的一篇博客上面已经详细的说明了,如果不明白可前往查看。

3.3 发布博客

上传完视频拿到播放地址以后,只需要发布一篇博客,并将视频的播放地址都发布到该博客上面即可。博客内容如下所示:
在这里插入图片描述
为了app自动获取特效的名称,需要在播放地址后面加上特效的名字,这样app特效的下拉框中就会自动填写这些特效名字。

4.camera使用

使用camerax来显示摄像头画面。camerax相比于camera2更加方便,兼容性更广。
使用camerax首先需要添加摄像头权限

<uses-feature android:name="android.hardware.camera.any" />
<uses-permission android:name="android.permission.CAMERA" />

添加相关依赖:

    //CameraX
    def camerax_version = "1.1.0-beta03"
// CameraX core library using camera2 implementation
    implementation "androidx.camera:camera-camera2:$camerax_version"
// CameraX Lifecycle Library
    implementation "androidx.camera:camera-lifecycle:$camerax_version"
// CameraX View class
    implementation "androidx.camera:camera-view:1.0.0-alpha24"

开启摄像头代码:

//开启摄像头
if(allPermissionsGranted()){
	startCamera(); //start camera if permission has been granted by user
} else{
	ActivityCompat.requestPermissions(this, REQUIRED_PERMISSIONS, 1001);
}

/**
 * 获取摄像头权限
 */
private final String[] REQUIRED_PERMISSIONS = new String[]{"android.permission.CAMERA", "android.permission.WRITE_EXTERNAL_STORAGE"};
private boolean allPermissionsGranted() {
    for (String permission : REQUIRED_PERMISSIONS) {
        if (ContextCompat.checkSelfPermission(this, permission) != PackageManager.PERMISSION_GRANTED) {
            return false;
        }
    }
    return true;
}


/**
* 开始预览
*/
private CameraControl cameraControl;
private Executor executor = Executors.newSingleThreadExecutor();
private void startCamera() {
   ListenableFuture<ProcessCameraProvider> cameraProviderFuture =
           ProcessCameraProvider.getInstance(this);
   ((ListenableFuture<?>) cameraProviderFuture).addListener(new Runnable() {
       @SuppressLint("RestrictedApi")
       @Override
       public void run() {
           try {

               ImageAnalysis imageAnalysis = new ImageAnalysis.Builder()
                       //.setBackpressureStrategy(ImageAnalysis.STRATEGY_BLOCK_PRODUCER)//阻塞模式
                       //.setOutputImageFormat(ImageAnalysis.OUTPUT_IMAGE_FORMAT_YUV_420_888)
                       //.setOutputImageFormat(ImageAnalysis.OUTPUT_IMAGE_FORMAT_RGBA_8888)
                       .build();
               imageAnalysis.setAnalyzer(executor, new ImageAnalysis.Analyzer() {
                   @Override
                   public void analyze(@NonNull @NotNull ImageProxy image) {

                       //yuv图像数据转bitmap
                       ImageProxy.PlaneProxy[] planes = image.getPlanes();
                       //cameraX 获取yuv
                       ByteBuffer yBuffer = planes[0].getBuffer();
                       ByteBuffer uBuffer = planes[1].getBuffer();
                       ByteBuffer vBuffer = planes[2].getBuffer();

                       int ySize = yBuffer.remaining();
                       int uSize = uBuffer.remaining();
                       int vSize = vBuffer.remaining();

                       byte[] nv21 = new byte[ySize + uSize + vSize];

                       yBuffer.get(nv21, 0, ySize);
                       vBuffer.get(nv21, ySize, vSize);
                       uBuffer.get(nv21, ySize + vSize, uSize);
                       //获取yuvImage
                       YuvImage yuvImage = new YuvImage(nv21, ImageFormat.NV21, image.getWidth(), image.getHeight(), null);
                       //输出流
                       ByteArrayOutputStream out = new ByteArrayOutputStream();
                       //压缩写入out
                       yuvImage.compressToJpeg(new Rect(0, 0, yuvImage.getWidth(), yuvImage.getHeight()), 50, out);
                       //转数组
                       byte[] imageBytes = out.toByteArray();
                       //生成bitmap
                       Bitmap bmp = BitmapFactory.decodeByteArray(imageBytes, 0, imageBytes.length);

//                            Bitmap rotateBitmap=null;

//                            Dector(bmp);

//                            Message message=new Message();
//                            message.what=2;
//                            message.obj=FPS;
//                            handler.sendMessage(message);


                       image.close();
                   }
               });



               //将相机的生命周期和activity的生命周期绑定,camerax 会自己释放
               ProcessCameraProvider cameraProvider = cameraProviderFuture.get();
               Preview preview = new Preview.Builder().build();
               //创建图片的 capture
               ImageCapture mImageCapture = new ImageCapture.Builder()
                       .setFlashMode(ImageCapture.FLASH_MODE_OFF)
                       .build();
               //选择前置摄像头
               CameraSelector cameraSelector = new CameraSelector.Builder().requireLensFacing(CameraSelector.LENS_FACING_BACK).build();
               // Unbind use cases before rebinding
               cameraProvider.unbindAll();

               // Bind use cases to camera
               //参数中如果有mImageCapture才能拍照,否则会报下错
               //Not bound to a valid Camera [ImageCapture:androidx.camera.core.ImageCapture-bce6e930-b637-40ee-b9b9-
               Camera camera = cameraProvider.bindToLifecycle(MainActivity.this, cameraSelector, preview, imageAnalysis,mImageCapture);

               cameraControl = camera.getCameraControl();
               cameraControl.setLinearZoom(0.1f);
               preview.setSurfaceProvider(pvCameraPreview.getSurfaceProvider());
           } catch (ExecutionException e) {
               e.printStackTrace();
           } catch (InterruptedException e) {
               e.printStackTrace();
           }
       }
   }, ContextCompat.getMainExecutor(this));
}

opengl片源渲染器代码:

"#extension GL_OES_EGL_image_external : require\n" +
"precision mediump float;" +
"uniform samplerExternalOES textureSampler;" +
"varying vec2 textureCoordinate;" +

"void main(){" +
"vec4 mycolor=texture2D(textureSampler,vec2(textureCoordinate.x,textureCoordinate.y/2.0));"+
"vec4 Alpha=texture2D(textureSampler,vec2(textureCoordinate.x,textureCoordinate.y/2.0+0.5));"+
"float alpha=1.0-(mycolor.r+mycolor.g+mycolor.b)/3.0;"+

"gl_FragColor=vec4(1.0-mycolor.rgb,alpha);" +

"}";

5.项目源码

手机端如果打不开链接,可以使用电脑试一下。
gitee地址:https://gitee.com/mqwdasddqw/SpecialEffect3

相关文章:

  • JAVA代码 企业人力资源管理系统(详细带截图) 毕业设计
  • Spring 事务
  • 海滩的海鸥
  • 医疗系统业务流程
  • 云计算-虚拟化
  • Vue学习之--------插槽【默认插槽、具名插槽、作用域插槽】(2022/8/30)
  • 医疗项目 01(项目简介)
  • 用npm 用jest测试
  • 版税激励错配下,创作者如何可持续地盈利?
  • 蓝桥杯实战应用【算法代码篇】-一题三解:计算二进制中1的个数(附Java和C++代码)
  • 一览「数字身份」市场结构:我们将在元宇宙中成为谁?
  • Web3 时代 市场营销的变迁
  • 常用类和内部类总结
  • 基于STM32的实时操作系统FreeRTOS移植教程(手动移植)
  • 每日简报 8月31日简报新鲜事 每天一分钟 了解新鲜事
  • 30秒的PHP代码片段(1)数组 - Array
  • Angular数据绑定机制
  • C# 免费离线人脸识别 2.0 Demo
  • java 多线程基础, 我觉得还是有必要看看的
  • Joomla 2.x, 3.x useful code cheatsheet
  • Tornado学习笔记(1)
  • 关于Android中设置闹钟的相对比较完善的解决方案
  • 关于List、List?、ListObject的区别
  • 基于 Babel 的 npm 包最小化设置
  • 聊聊hikari连接池的leakDetectionThreshold
  • 数据可视化之 Sankey 桑基图的实现
  • 思考 CSS 架构
  • 详解移动APP与web APP的区别
  • 字符串匹配基础上
  • 3月27日云栖精选夜读 | 从 “城市大脑”实践,瞭望未来城市源起 ...
  • Nginx惊现漏洞 百万网站面临“拖库”风险
  • zabbix3.2监控linux磁盘IO
  • 从如何停掉 Promise 链说起
  • 继 XDL 之后,阿里妈妈开源大规模分布式图表征学习框架 Euler ...
  • 微龛半导体获数千万Pre-A轮融资,投资方为国中创投 ...
  • ​LeetCode解法汇总2182. 构造限制重复的字符串
  • ###C语言程序设计-----C语言学习(3)#
  • #vue3 实现前端下载excel文件模板功能
  • #我与Java虚拟机的故事#连载11: JVM学习之路
  • #预处理和函数的对比以及条件编译
  • (1)(1.13) SiK无线电高级配置(五)
  • (HAL库版)freeRTOS移植STMF103
  • (NO.00004)iOS实现打砖块游戏(九):游戏中小球与反弹棒的碰撞
  • (附源码)ssm航空客运订票系统 毕业设计 141612
  • (一)基于IDEA的JAVA基础12
  • .NET Core 中的路径问题
  • .Net 访问电子邮箱-LumiSoft.Net,好用
  • .NET 中 GetHashCode 的哈希值有多大概率会相同(哈希碰撞)
  • .net6 webapi log4net完整配置使用流程
  • .NET连接MongoDB数据库实例教程
  • .NET设计模式(8):适配器模式(Adapter Pattern)
  • .Net中间语言BeforeFieldInit
  • [AIGC] 开源流程引擎哪个好,如何选型?
  • [EFI]MSI GF63 Thin 9SCXR电脑 Hackintosh 黑苹果efi引导文件
  • [Flex] PopUpButton系列 —— 控制弹出菜单的透明度、可用、可选择状态