首页 > 其他分享 >Android平台RTMP推送|轻量级RTSP服务|GB28181设备接入模块之实时快照保存JPG还是PNG?

Android平台RTMP推送|轻量级RTSP服务|GB28181设备接入模块之实时快照保存JPG还是PNG?

时间:2024-01-14 11:01:24浏览次数:40  
标签:快照 name GB28181 image 轻量级 file new PNG String

JPG还是PNG?

JPG和PNG是两种常见的图片文件格式,在压缩方式、图像质量、透明效果和可编辑性等方面存在显著差异。

  • 压缩方式:JPG是一种有损压缩格式,通过丢弃图像数据来减小文件大小,因此可能会损失一些图像细节和质量。而PNG使用的是无损压缩格式,它不会丢失任何原始图像数据,从而保持了图像的完整性和质量。
  • 图像质量:由于压缩方式的不同,JPG在压缩后会牺牲一部分图像数据,因此在图像质量上可能存在损失,例如可能会出现锯齿状边缘或颜色失真。相比之下,PNG的无损压缩可以保证原图像数据的完整性,其256个透明层次的设定可以使图片边缘平滑融合,从而消除图片锯齿边缘。
  • 透明效果:PNG支持透明度,可以用作背景透明的图片,而JPG则不支持透明效果。因此,如果你需要制作半透明的图像或者需要背景透明的图片,PNG是一个更好的选择。
  • 可编辑性:JPG是一种不可编辑的图片格式,一旦被保存为JPG格式,就无法进行修改。而PNG是一种可编辑的图片格式,可以通过图像编辑软件(如Photoshop)进行修改、编辑和重新保存。例如,你可以改变PNG图片中的文字样式、线条等元素。

Android推流端的截图设计

大牛直播SDK早期在做Android平台RTMP推流和轻量级RTSP服务模块的时候,截图考虑到PNG的特性,直接保存png图片,随着GB28181-2022规范的实施,规范里面有明确要求,需要支持JPG编码,为此我们针对截图这块,做了如下的调整(对应:实时快照):

Android平台RTMP推送|轻量级RTSP服务|GB28181设备接入模块之实时快照保存JPG还是PNG?_RTMP快照

原接口:

/**
	  * 请使用新的CaptureImage接口, 这个接口只能保存PNG图片, 不推荐使用
	  * Save current image during publishing stream(实时快照)
	  *
	  * @param imageName: image name, which including fully path, "/sdcard/daniuliveimage/daniu.png", etc.
	  *
	  * @return {0} if successful
	  */
	 public native int SmartPublisherSaveCurImage(long handle,  String imageName);

值得注意的是,原接口如果需要截图,还需要调用SmartPublisherSaveImageFlag()。

新的接口,我们设计如下:

/**
	 * 新的截图接口, 支持JPEG和PNG两种格式
	 * @param compress_format: 压缩格式, 0:JPEG格式, 1:PNG格式, 其他返回错误
	 * @param quality: 取值范围:[0, 100], 值越大图像质量越好, 仅对JPEG格式有效, 若是PNG格式,请填100
	 * @param file_name: 图像文件名, 例如:/dirxxx/test20231113100739.jpeg, /dirxxx/test20231113100739.png
	 * @param user_data_string: 用户自定义字符串
	 * @return {0} if successful
	 */
	 public native int CaptureImage(long handle, int compress_format, int quality, String file_name, String user_data_string);

如何调用?

废话不多说,直接上代码:

private SimpleDateFormat capture_image_date_format_;

    class ButtonCaptureImageListener implements OnClickListener {
        @SuppressLint("SimpleDateFormat")
        public void onClick(View v) {
            if(isPushingRtmp || isRecording || isRTSPPublisherRunning || isPushingRtsp)
            {
                if (null == capture_image_date_format_)
                    capture_image_date_format_ = new SimpleDateFormat("yyyyMMddHHmmssSSS");

                String timeStamp = capture_image_date_format_.format(new Date());
                String imageFileName = timeStamp;    //创建以时间命名的文件名称

                String imagePath = imageSavePath + "/" + imageFileName;

                int quality;
                boolean is_jpeg = true;
                if (is_jpeg) {
                    imagePath += ".jpeg";
                    quality = 100;
                }
                else {
                    imagePath += ".png";
                    quality = 100;
                }

                int capture_ret = libPublisher.CaptureImage(publisherHandle,is_jpeg?0:1, quality, imagePath, "test_user_data");
                Log.i(TAG, "capture_image ret:" + capture_ret + ", file:" + imagePath);
            }
            else
            {
                Log.e(TAG, "快照失败,请确保在推送、录像或内置RTSP服务发布状态..");
            }
        }
    }

截图成功,对应的event回调如下:

class EventHandeV2 implements NTSmartEventCallbackV2 {
        @Override
        public void onNTSmartEventCallbackV2(long handle, int id, long param1, long param2, String param3, String param4, Object param5) {

            Log.i(TAG, "EventHandeV2: handle=" + handle + " id:" + id);

            String publisher_event = "";

            switch (id) {
                .....

                case NTSmartEventID.EVENT_DANIULIVE_ERC_PUBLISHER_CAPTURE_IMAGE:
                    publisher_event = "快照: " + param1 + " 路径:" + param3;
                    if (0 == param1) {
                        rename_image_file_name(param3, param2);
                        publisher_event = publisher_event + "截取快照成功.." + ", 用户数据:" + param4;
                    } else
                        publisher_event = publisher_event + "截取快照失败..";

                    break;
                    ....
        }
    }

如果需要对截图后的文件重命名(比如gb28181,我们会把截图时间返上来),便于统一管理,参考代码如下:

private void rename_image_file_name(String file_name, long file_date_time_ms) {
        if (null == file_name || file_name.isEmpty()
                || file_date_time_ms < 1 || null == capture_image_date_format_)
            return;

        try {
            java.io.File file = new File(file_name);
            if (!file.exists() || !file.isFile() || !file.canRead() || file.length() < 1)
                return;

            String file_name_extension = null;
            int index = file_name.lastIndexOf('.');
            if (index > -1)
                file_name_extension = file_name.substring(index + 1);

            Date file_date = new Date(file_date_time_ms);
            String new_file_name = capture_image_date_format_.format(file_date);
            if (file_name_extension != null && !file_name_extension.isEmpty())
                new_file_name += "." + file_name_extension;

            java.io.File new_file = new java.io.File(file.getParent(), new_file_name);
            if (file.renameTo(new_file))
                Log.i(TAG, "rename image file name ok, file_name:" + file_name + ", new:"+ new_file_name);
             else
                Log.e(TAG, "rename image file name failed, file_name:" + file_name);

        } catch (Exception e) {
            Log.e(TAG, "rename_image_file_name Exception:", e);
        }
    }

总结

Android平台RTMP推送、轻量级RTSP还是GB28181设备对接模块,选择哪种图片格式主要取决于具体的使用需求。如果你需要压缩图像文件并且不关心原始图像的完整性,JPG可能是一个更好的选择。而如果你需要保持原始图像的完整性和质量,或者需要制作背景透明的图片,那么PNG可能是更好的选择。


标签:快照,name,GB28181,image,轻量级,file,new,PNG,String
From: https://blog.51cto.com/daniusdk/9239524

相关文章

  • 从Bitcask存储模型谈超轻量级KV系统设计与实现
    Bitcask介绍Bitcask是一种“基于日志结构的哈希表”(ALog-StructuredHashTableforFastKey/ValueData)Bitcask最初作为分布式数据库Riak的后端出现,Riak中的每个节点都运行一个Bitcask实例,各自存储其负责的数据。抛开论文,我们先通过一篇博客#Bitcask—alog-struc......
  • 无涯教程-Maven - 快照
    SNAPSHOT是一个特殊版本,指示当前的开发副本,与常规版本不同,Maven为每个构建都在远程存储库中检查新的SNAPSHOT版本。现在,数据服务团队将每次将SNAPSHOT更新的代码发布到存储库中,例如数据服务:1.0-SNAPSHOT,将替换旧的SNAPSHOTjar。快照与版本对于Version,如果Maven一旦下载了提......
  • 界面组件DevExpress WPF v23.2 - 更轻量级的主题支持
    DevExpressWPFSubscription拥有120+个控件和库,将帮助您交付满足甚至超出企业需求的高性能业务应用程序。通过DevExpressWPF能创建有着强大互动功能的XAML基础应用程序,这些应用程序专注于当代客户的需求和构建未来新一代支持触摸的解决方案。DevExpressWPF控件日前正式发布了......
  • GB28181视频汇聚平台EasyCVR级联后,部分通道视频无法播放是什么原因?
    国标GB28181安防监控EasyCVR平台能通过标准接口与标准协议与第三方平台级联,实现视频资源的互通共享、共用,EasyCVR既能作为上级平台与下级级联,也能作为下级平台级联到上级监管平台。有用户反馈,下级平台级联到EasyCVR平台后,有的通道能正常播放,但是大部分通道无法播放,于是请求我们排查......
  • LiveGBS流媒体平台GB/T28181常见问题-如何配置快照目录快照存储默认目录目录如何配置
    LiveGBS流媒体平台GB/T28181常见问题-如何配置快照目录快照存储默认目录目录如何配置1、快照目录2、指定快照目录3、搭建GB28181视频直播平台1、快照目录部署LiveGBS后,再查看通道播放后或是获取通道快照后,就会在LiveSMS部署的服务器里面存储对应的最新快照,默认的快照目录是Li......
  • LiveNVR监控流媒体Onvif/RTSP常见问题-如何配置快照目录快照存储默认目录目录如何配置
    LiveNVR监控流媒体Onvif/RTSP常见问题-如何配置快照目录快照存储默认目录目录如何配置?1、快照目录2、指定快照目录3、RTSP/HLS/FLV/RTMP拉流Onvif流媒体服务1、快照目录部署LiveNVR后,配置通道上线后,会在LiveNVR部署的服务器里面存储对应的最新快照,默认的快照目录是LiveNVR解......
  • 简洁、轻量级的 Go API 框架
    本次分享的框架是「gin-api-mono」介绍gin-api-mono前先了解go-gin-apigo-gin-api这是一个基于Gin的API框架,它提供了WEB界面一键安装的方式,让你可以快速启动一个开箱即用的Go项目。无论你是否有项目经验,这个框架都适合作为练手项目使用(新手入门必备)。该框架采用了......
  • 在VM下使用Composer完成快照方式的软件制作
    Composer允许您构建软件、应用程序、偏好设置文件或是文档的安装包,安装包可以部署到远程电脑或是作为镜像流程的一部分。构建软件包的第一步就是创建包源,根据要打包的软件,Composer允许您监视软件的安装和使用驱动器上已存在的文件来创建包源。创建包源后,可以构建成PKG或DMG的安装包......
  • Android GB28181-2022 图像抓拍
     GB28181-2022新增图像抓拍功能,这个功能很有用,无需在设备实时点播的情况下,就可以抓图上传到指定的图像存储服务器上。如果配置合适的抓拍间隔,JPEG也选择适当的压缩参数,相比实时音视频回传更省流量,设备功耗也低。 GB28181图像抓拍分为三步,一是下发图像抓拍配置命令给设备,......
  • GB28181视频监控平台LiteCVR调用rtsp地址返回的IP不正确原因排查
    RTSP(Real-TimeStreamingProtocol)是一种用于控制实时流媒体传输的应用层协议。它被设计用于建立和管理客户端与媒体服务器之间的连接,以便实现实时音频、视频或其他交互式媒体内容的传输。RTSP允许客户端通过发送命令来控制流媒体服务器的播放、暂停、快进、倒带等操作。RTSP支持多......