精华内容
下载资源
问答
  • 屏幕录制成gif工具

    2019-04-30 17:38:55
    屏幕录像成GIF工具:主要是通过选定屏幕范围后确认开始录制录制后会生成GIF文件
  • 屏幕录制成gif动画

    2016-12-04 11:14:26
    可以录制屏幕,保存成gif格式的图片,支持帧的添加删除和,图片大小处理,添加滤镜等。
  • 前言:上篇中,介绍是用MediaMuxer与MediaExtractor进入音视频的裁剪,今天用MediaMuxer与AudioRecord与MediaCodec及Surface进行屏幕录制成gif。看下Agenda

    转载请把头部出处链接和尾部二维码一起转载,本文出自逆流的鱼yuiop:http://blog.csdn.net/hejjunlin/article/details/53866405

    前言:上篇中,介绍是用MediaMuxer与MediaExtractor进入音视频的裁剪,今天用MediaMuxer与AudioRecord与MediaCodec及Surface进行屏幕录制成gif。看下Agenda:

    • 效果图
    • 主体思路
    • 转gif两种方案

    MediaMuxer是用于将音频和视频进行混合生成多媒体文件。缺点是目前只能支持一个audio track和一个video track,而且仅支持mp4输出。

    效果图1:操作步骤


    这里写图片描述

    效果图2:注意效果图里的gif就是最终产生的录制屏幕后产生的


    这里写图片描述

    主体思路:

    逻辑:录屏不需要操作视频原始数据,因此使用InputSurface作为编码器的输入。

    视频:MediaProjection通过createVirtualDisplay创建的VirtualDisplay传入的Surface是通过MediaCodec的createInputSurface方法返回的,【本文出自逆流的鱼yuiop:http://blog.csdn.net/hejjunlin/article/details/53866405】表明编码器的输入其实来自于录制到的屏幕数据,于是只需要在MediaCodec的输出缓冲区中拿到编码后的ByteBuffer即可。

    音频:录制程序获得音频原始数据PCM,传给MediaCodec编码,然后从MediaCodec的输出缓冲区拿到编码后的ByteBuffer即可。

    最终通过合并模块将音视频混合。

    视频:MediaProjection通过createVirtualDisplay创建的VirtualDisplay传入的Surface是通过ImageReader的getSurface方法返回的,表明录制的屏幕帧数据传递到ImageReader,于是通过ImageReader的相关API可以读取到录制的屏幕每一帧的数据

    音频:由于录制的就是原始PCM编码的音频数据,因此录制到音频数据后直接调用AudioRecord即可。

    简单说就是重定向了屏幕录制的数据的方向,这个Surface提供的是什么,录制的视频数据就传到哪里。Surface提供的是本地某个SurfaceView控件,那么就会将屏幕内容显示到这个控件上,提供MediaCodec就是作为编码器的输入源最终获得编码后的数据,提供ImageReader就会作为ImageReader的数据源,最终获得了视频的原始数据流。

    由于录制的是视频,得变成gif,有两种方案:

    • 提取视频文件->解析视频->提取 Bitmap 序列(使用 MediaMetadataRetriever 提取某一时刻的图片,然后把很多某一时刻的图片串联起来编码成 gif。看来其也正是 gif 的原理,但实现出来的效果极差,无法准确提取到准确的图片,导致合成的 gif 图也无法连贯播放,播放起来也跳帧跳得很厉害。可以用惨不忍睹来形容)
    • 利用FFmpeg直接转gif, 这个在我的《FFmpeg在Linux下安装编译过程》一文中,就是把编译出来库,进行演示转gif,当时是SuperIndicator的gif。对于把Android上,也是同样的原理。这种方法岗岗的。

    方案一思路

    视频文件的解析

    视频文件读取成功后,接下来要做的就是解析视频文件,选取需要转换的视频片段,提取 Bitmap 序列。下面来看下具体实现,提取 Bitmap 序列就是根据给定的起始时间和结束时间以及帧率从视频文件中获取相应的 Bitmap,这种思路主要是利用 MediaMetadataRetriever 提供的 API 来实现的,在看代码前可以先看下 MediaMetadataRetriever 的 API 文档,该类的核心功能就是获取视频的帧和元数据,下面是核心实现代码:

    public List<Bitmap> createBitmaps(String path) {
      MediaMetadataRetriever mmr = new MediaMetadataRetriever();
      mmr.setDataSource(path);
      double inc = 1000 * 1000 / fps;
    
      for (double i = begin; i < end; i += inc) {
        Bitmap frame = mmr.getFrameAtTime((long) i, MediaMetadataRetriever.OPTION_CLOSEST);
        if (frame != null) {
          bitmaps.add(scale(frame));
        }
      }
    
      return bitmaps;
    }
    
    private Bitmap scale(Bitmap bitmap) {
      return Bitmap.createScaledBitmap(bitmap,
        width > 0 ? width : bitmap.getWidth(),
        height > 0 ? height : bitmap.getHeight(),
        true);
    }

    拿到要生成 GIF 的 Bitmap 序列,接下来需要做的就是将 Bitmap 序列中的数据按照 GIF 的文件格式编码,生成最终的 GIF 文件。目标很明确,接下来就看具体实现过程了。

    GIF 格式简介

    生成 GIF 文件之前有必要介绍下 GIF 的存储格式,只是简单说下后面程序中会用到的方面。
    GIF 图象是基于颜色列表的(存储的数据是该点的颜色对应于颜色列表的索引值),最多只支持 8 位(256 色)。GIF 文件内部分成许多存储块,用来存储多幅图象或者是决定图象表现行为的控制块,用以实现动画和交互式应用。GIF 文件还通过 LZW 压缩算法压缩图象数据来减少图象尺寸。
    GIF 文件内部是按块划分的,包括控制块和数据块两种。控制块是控制数据块行为的,根据不同的控制块包含一些不同的控制参数;数据块只包含一些 8-bit 的字符流,由它前面的控制块来决定它的功能,每个数据块 0 到 255 个字节,数据块的第一个字节指出这个数据块大小(字节数),计算数据块的大小时不包括这个字节,所以一个空的数据块有一个字节,那就是数据块的大小0x00。

    GIF 文件写入

    刚开始接触 GIF 文件会觉得比较复杂,存储格式、编码格式等都比 Bitmap 要复杂的多,但其实可以把问题简单化理解,生成 GIF 和生成 Bitmap 原理类似,就是按照规定的格式写文件就行了,不用太纠结内部细节,否则就会陷入繁琐的细节,而忽略了最终目的只是为了生成 GIF 文件。下面就来看下有哪些文件部分需要写入的:

    提取 Bitmap 的像素值
    首先需要将上面得到的 Bitmap 的像素值提取出来,方便后面把像素值写入到 GIF 文件中,在提取像素值的同时,生成 GIF 文件所需要的颜色表,生成颜色表过程比较复杂,这里就不贴出源码,感兴趣的可以Google一下颜色量化算法,不感兴趣的直接用现成的就好,下面是提取像素值的具体实现:

    protected void getImagePixels() {
     int w = image.getWidth();
     int h = image.getHeight();
     pixels = new byte[w*h*3];
     for (int i = 0; i < h; i++) {
     int stride = w * 3 * i;
     for (int j = 0; j < w; j++) {
      int p = image.getPixel(j, i);
      int step = j * 3;
      int offset = stride + step;
      // blue
      pixels[offset+0] = (byte) ((p & 0x0000FF) >> 0);
      // green
      pixels[offset+1] = (byte) ((p & 0x00FF00) >> 8);
      // red
      pixels[offset+2] = (byte) ((p & 0xFF0000) >> 16); 
     }
     }
    }

    GIF 文件头(Header)
    文件头部分总共 6 个字节,包括:GIF 署名和版本号,GIF 署名由 3 个字符”GIF”组成,共 3 个字节,版本号也是由 3 个字节组成,可以为”87a”或”89a”(分别为 1987 年和 1989 年版本),实现代码如下:

    // 写入文件头
    protected void writeHeader() throws IOException {
     writeString("GIF89a");
    }
    
    protected void writeString(String s) throws IOException {
     for (int i = 0; i < s.length(); i++) {
     out.write((byte) s.charAt(i));
     }
    }

    逻辑屏幕标识符(Logical Screen Descriptor)
    文件头的后面是逻辑屏幕标识符(Logical Screen Descriptor),这一部分由 7 个字节组成,定义了 GIF 图象的大小、颜色深度、背景色以及有无全局颜色列表和颜色列表的索引数。实现代码如下:

    // 写入逻辑屏幕标识符

    protected void writeLSD() throws IOException {
     writeShort(width); // 写入图像宽度
     writeShort(height); // 写入图像高度
    
     out.write((0x80 | // 全局颜色列表标志置 1
        0x70 | // 确定图象的颜色深度(7+1=8)
        0x00 | // 全局颜色列表分类排列置为 0
        0x07)); // 颜色列表的索引数(2的7+1次方)
    
     out.write(0); // 背景颜色(在全局颜色列表中的索引)
     out.write(0); // 像素宽高比默认 1:1
    }
    
    protected void writeShort(int value) throws IOException {
     out.write(value & 0xff);
     out.write((value >> 8) & 0xff);
    }

    逻辑屏幕标识符部分结构稍微复杂些,如果不知道每一位代表什么意思可以参考:GIF图形文件格式文档 中的逻辑屏幕标识符部分。
    全局颜色列表(Global Color Table)
    全局颜色列表必须紧跟在逻辑屏幕标识符后面,每个颜色列表索引条目由三个字节组成,按R、G、B的顺序排列,具体生成颜色表的实现可以看源码部分,由于生成过程比较复杂,【本文出自逆流的鱼yuiop:http://blog.csdn.net/hejjunlin/article/details/53866405】这里就不贴颜色表生成的代码了,下面是写入颜色表的代码:

    // 写入颜色表
    protected void writePalette() throws IOException {
     out.write(colorTab, 0, colorTab.length);
     int n = (3 * 256) - colorTab.length;
     for (int i = 0; i < n; i++) {
     out.write(0);
     }

    图形控制扩展(Graphic Control Extension)
    这一部分是可选的,89a 版本才支持,可以放在一个图象块(包括图象标识符、局部颜色列表和图象数据)或文本扩展块的前面,用来控制跟在它后面的第一个图象(或文本)的渲染( Render )形式,下面实现代码:

    protected void writeGraphicCtrlExt() throws IOException {
     out.write(0x21); // 扩展块标识,固定值 0x21
     out.write(0xf9); // 图形控制扩展标签,固定值 0xf9
     out.write(4); // 块大小,固定值 4
     out.write(0 | // 1:3 保留位
       0 | // 4:6 不使用处置方法
       0 | // 7 用户输入标志置 0
       0); // 8 透明色标志置 0
    
     writeShort(delay); // 延迟时间
     out.write(0);  // 透明色索引值
     out.write(0);  // 块终结器,固定值 0
    }

    图象标识符(Image Descriptor)
    一个 GIF 文件内可以包含多幅图象,一幅图象结束之后紧接着下是一幅图象的标识符,图象标识符以 0x2C(‘,’)字符开始,定义紧接着它的图象的性质,包括图象相对于逻辑屏幕边界的偏移量、图象大小以及有无局部颜色列表和颜色列表大小,由10个字节组成,下面是实现代码:

    protected void writeImageDesc() throws IOException {
     out.write(0x2c); // 图象标识符开始,固定值为 0x2c
     writeShort(0);  // x 方向偏移
     writeShort(0);  // y 方向偏移
     writeShort(width); // 图像宽度
     writeShort(height); // 图像高度
     out.write((
      0x80 |  // 局部颜色列表标志置 1
      0x00 |
      0x00 |
      0x07));  // 局部颜色列表的索引数(2的7+1次方)
    }

    图象数据(Image Data)
    GIF 图象数据使用了 LZW 压缩算法,大大减小了图象数据的大小,具体的 LZW 压缩算法可以Google一下,下面是图像数据的写入实现:

    protected void writePixels() throws IOException {
     LZWEncoder encoder = new LZWEncoder(
      width, height, indexedPixels, colorDepth);
     encoder.encode(out);
    }

    文件终结器(Trailer)
    这一部分只有一个字节,标识一个GIF文件结束,固定值为 0x3B,实现代码:

    public void finish() throws IOException {
     out.write(0x3b);
     out.flush();
     out.close();
    }

    总结
    到目前为止,将 MP4 文件转换为 GIF 文件的实现过程基本完成,如果需要对 GIF 文件进行裁剪、添加水印等处理的话,可以在 Bitmap 序列写入 GIF 之前,对【本文出自逆流的鱼yuiop:http://blog.csdn.net/hejjunlin/article/details/53866405】 Bitmap 进行相应的处理即可

    方案二思路:

    编译so文件过程:

    这里写图片描述

    编译最后产生so,会自动生成一个libs目录:

    这里写图片描述

    点击进入libs目录,可以发现一个是arm平台的so文件夹,一个是x86平台的so文件夹:

    这里写图片描述

    随便点击一个,进入,就是一些so:

    这里写图片描述

    体验 apk

    下载地址:链接: https://pan.baidu.com/s/1skR35nB 密码: 2wb3

    第一时间获得博客更新提醒,以及更多android干货,源码分析,欢迎关注我的微信公众号,扫一扫下方二维码或者长按识别二维码,即可关注。

    这里写图片描述

    如果你觉得好,随手点赞,也是对笔者的肯定,也可以分享此公众号给你更多的人,原创不易

    资料参考:(http://www.jb51.net/article/91305.htm

    展开全文
  • 屏幕录制成gif格式

    2011-10-23 09:23:19
    让我们很轻松的制作出gif格式的教程,节省空间。
  • 需要向别人展示一些操作或是效果,如果单纯截图片有时难以说清楚,录制成视频有点大,发送不方便,所以生成动态图方便,下面我们就介绍一些好用的录制屏幕成git的软件: 一、功能最多的开源软件---screentogif, ...

    需要向别人展示一些操作或是效果,如果单纯截成图片有时难以说清楚,录制成视频有点大,发送不方便,所以生成动态图方便,下面我们就介绍一些好用的录制屏幕成git的软件:

    一、功能最多的开源软件---screentogif,

    1.下载:去screentogif官网下载软件,可以下载安装版本也可以下载不用安装版本,screentogif官网:https://www.screentogif.com/ 。

    github:https://github.com/NickeManarin/ScreenToGif 。

    github下载页面:https://github.com/NickeManarin/ScreenToGif/releases/tag/2.14.1

    2.使用方法:

    打开软件录制,如果录屏或者录制git,点击“录像机”,然后会出现录制屏幕选择框可以缩放拉伸等操作,可以随意拖动边框调整屏幕捕获窗口的大小。

     

     

    录制好后可以点击“停止”,或者使用F7键开始/暂停F8停止录制。录制完成后在编辑界面下方会显示具体的每一帧(点击菜单项View可以播放方才录制的动图),有哪一帧不想要的可以直接删除

     

    另存为是保存,可以右边设置保持成git还是视频等格式,最后别忘记点保存,并指定保存位置。如下面最后的演示,

    也可以打开软件后点击“画板”录制画板。然后就会弹出界面,然后写自己想写的内容,然后就可以录制了,之后的步骤和录制gif或者录屏一样。录制的效果如下:

    二、灵活好用,GIF 屏幕录制工具--LICEcap 。

    LICEcap 是一款屏幕录制工具,支持导出 GIF 动画图片格式,轻量级、使用简单,录制过程中可以随意改变录屏范围,LICEcap 非常轻量级,安装包不到 500KB。运行后会以窗口的方式显示在桌面,拖动选取一个合适的大小范围,点击 Record 选取保存路径就开始录屏了。LICEcap 在录屏过程中可以随时拖动窗口改变录屏范围,Stop 过后自动保存为 GIF 格式。录制过程中,按暂停可以插入文字(测试只支持插入英文)

    功能:录制为.GIF或.LCF。录制过程中,可移动捕捉框,从而改变录制范围。暂停/重新开始录制,并可插入文字(暂不支持中文)说明帧。录制过程中,可用全局热键 (shift+space) 暂停/继续。录制帧频可调,以便于平衡CPU占用率。设定标题帧,显示基本信息。录制鼠标按下动作。录制时,显示时间。

    官方主页:http://www.cockos.com/licecap/

    源码:git clone https://www-dev.cockos.com/licecap/licecap.git

    Official GitHub mirror: github.com/justinfrankel/licecap

    效果演示:

    三、轻量却超强的截屏幕+录屏软件---FScapture:这个录屏 轻量却超强——,它本来是一款截图软件,同时带了屏幕录制的功能,输出为WMV格式。FScapture屏幕录制是不支持GIF输出的,实在遗憾,之所以推荐它是因为这款软件同时也是截图工具,它带了屏幕录制功能,没有特殊需要就不用再下别的软件了。弥补缺陷,推荐使用qq影音视频转GIF的工具。

    FScapture的屏幕录制

    四、好用的录制屏幕成Gif的软件--Honeycam:

    Honeycam提供各种编辑工具和效果。

    另外录制gif软件还有ShareX, 下载地址:https://github.com/ShareX/ShareX。录屏成gif动画图的软件众多,不一一推荐。基本上前三款已经能满足大部分的录制屏幕需要的,甚至第一款已经足够应付所有的录屏成gif动画的需求了,怎么样?以后录制课件、录制指导的操作,是不是容易的多了?

    感谢关注和支持!

     

    转载文章,原链接:https://baijiahao.baidu.com/s?id=1614038292774609233&wfr=spider&for=pc

    展开全文
  • 写博客想要录制自己的程序效果,分享一款屏幕直接录制成gif图并保存的软件–ScreenToGif。下载链接: http://download.csdn.net/detail/rosechan/9487795

    写博客想要录制自己的程序效果,分享一款屏幕直接录制成gif图并保存的软件–ScreenToGif。

    下载链接:

    http://download.csdn.net/detail/rosechan/9487795

    展开全文
  • 前言:一直以来,很多做apk演示效果时,通过图片的方式,总是没有看起来那样炫丽和灵动。如果能在手机上,直接通过录制屏幕,而变成gif。那可是省去了好多时间。进而可以做其他的价值的事情。今...

    前言:一直以来,很多做apk演示效果时,通过图片的方式,总是没有看起来那样炫丽和灵动。如果能在手机上,直接通过录制屏幕,而变成gif。那可是省去了好多时间。进而可以做其他的价值的事情。今天分享是一种手机上实现屏幕录制成gif的方案。接Android Multimedia框架总结系列,本文是我总结第二十四篇Multimedia框架文章。

    在第二十三篇中介绍是用MediaMuxer与MediaExtractor进入音视频的裁剪,可查看【Android Multimedia框架总结(二十三)MediaCodec补充及MediaMuxer引入(附案例)】今天用MediaMuxer与AudioRecord与MediaCodec及Surface进行屏幕录制成gif。看下Agenda:

    • 效果图

    • 主体思路

    • 转gif两种方案

    MediaMuxer是用于将音频和视频进行混合生成多媒体文件。缺点是目前只能支持一个audio track和一个video track,而且仅支持mp4输出。

    效果图1:操作步骤 



     

    效果图2:注意效果图里的gif就是最终产生的录制屏幕后产生的 


     

    主体思路:

    逻辑:录屏不需要操作视频原始数据,因此使用InputSurface作为编码器的输入。

    视频:MediaProjection通过createVirtualDisplay创建的VirtualDisplay传入的Surface是通过MediaCodec的createInputSurface方法返回的,表明编码器的输入其实来自于录制到的屏幕数据,于是只需要在MediaCodec的输出缓冲区中拿到编码后的ByteBuffer即可。

    音频:录制程序获得音频原始数据PCM,传给MediaCodec编码,然后从MediaCodec的输出缓冲区拿到编码后的ByteBuffer即可。

    最终通过合并模块将音视频混合。

    视频:MediaProjection通过createVirtualDisplay创建的VirtualDisplay传入的Surface是通过ImageReader的getSurface方法返回的,表明录制的屏幕帧数据传递到ImageReader,于是通过ImageReader的相关API可以读取到录制的屏幕每一帧的数据

    音频:由于录制的就是原始PCM编码的音频数据,因此录制到音频数据后直接调用AudioRecord即可。

    简单说就是重定向了屏幕录制的数据的方向,这个Surface提供的是什么,录制的视频数据就传到哪里。Surface提供的是本地某个SurfaceView控件,那么就会将屏幕内容显示到这个控件上,提供MediaCodec就是作为编码器的输入源最终获得编码后的数据,提供ImageReader就会作为ImageReader的数据源,最终获得了视频的原始数据流。

    由于录制的是视频,得变成gif,有两种方案:

    • 提取视频文件->解析视频->提取 Bitmap 序列(使用 MediaMetadataRetriever 提取某一时刻的图片,然后把很多某一时刻的图片串联起来编码成 gif。看来其也正是 gif 的原理,但实现出来的效果极差,无法准确提取到准确的图片,导致合成的 gif 图也无法连贯播放,播放起来也跳帧跳得很厉害。可以用惨不忍睹来形容)

    • 利用FFmpeg直接转gif, 这个在我的《FFmpeg在Linux下安装编译过程》一文中,就是把编译出来库,进行演示转gif,当时是SuperIndicator的gif。对于把Android上,也是同样的原理。这种方法岗岗的。

    方案一思路

    视频文件的解析

    视频文件读取成功后,接下来要做的就是解析视频文件,选取需要转换的视频片段,提取 Bitmap 序列。下面来看下具体实现,提取 Bitmap 序列就是根据给定的起始时间和结束时间以及帧率从视频文件中获取相应的 Bitmap,这种思路主要是利用 MediaMetadataRetriever 提供的 API 来实现的,在看代码前可以先看下 MediaMetadataRetriever 的 API 文档,该类的核心功能就是获取视频的帧和元数据,下面是核心实现代码:

    public List<Bitmap> createBitmaps(String path) {
      MediaMetadataRetriever mmr = new MediaMetadataRetriever();
      mmr.setDataSource(path);
      double inc = 1000 * 1000 / fps;
      for (double i = begin; i < end; i += inc) {
        Bitmap frame = mmr.getFrameAtTime((long) i, MediaMetadataRetriever.OPTION_CLOSEST);
        if (frame != null) {
          bitmaps.add(scale(frame));
        }
      }
      return bitmaps;
    }
    private Bitmap scale(Bitmap bitmap) {
      return Bitmap.createScaledBitmap(bitmap,
        width > 0 ? width : bitmap.getWidth(),
        height > 0 ? height : bitmap.getHeight(),
        true);
    }
    

    拿到要生成 GIF 的 Bitmap 序列,接下来需要做的就是将 Bitmap 序列中的数据按照 GIF 的文件格式编码,生成最终的 GIF 文件。目标很明确,接下来就看具体实现过程了。

    GIF 格式简介

    生成 GIF 文件之前有必要介绍下 GIF 的存储格式,只是简单说下后面程序中会用到的方面。 
    GIF 图象是基于颜色列表的(存储的数据是该点的颜色对应于颜色列表的索引值),最多只支持 8 位(256 色)。GIF 文件内部分成许多存储块,用来存储多幅图象或者是决定图象表现行为的控制块,用以实现动画和交互式应用。GIF 文件还通过 LZW 压缩算法压缩图象数据来减少图象尺寸。 
    GIF 文件内部是按块划分的,包括控制块和数据块两种。控制块是控制数据块行为的,根据不同的控制块包含一些不同的控制参数;数据块只包含一些 8-bit 的字符流,由它前面的控制块来决定它的功能,每个数据块 0 到 255 个字节,数据块的第一个字节指出这个数据块大小(字节数),计算数据块的大小时不包括这个字节,所以一个空的数据块有一个字节,那就是数据块的大小0x00。

    GIF 文件写入

    刚开始接触 GIF 文件会觉得比较复杂,存储格式、编码格式等都比 Bitmap 要复杂的多,但其实可以把问题简单化理解,生成 GIF 和生成 Bitmap 原理类似,就是按照规定的格式写文件就行了,不用太纠结内部细节,否则就会陷入繁琐的细节,而忽略了最终目的只是为了生成 GIF 文件。下面就来看下有哪些文件部分需要写入的:

    提取 Bitmap 的像素值 
    首先需要将上面得到的 Bitmap 的像素值提取出来,方便后面把像素值写入到 GIF 文件中,在提取像素值的同时,生成 GIF 文件所需要的颜色表,生成颜色表过程比较复杂,这里就不贴出源码,感兴趣的可以Google一下颜色量化算法,不感兴趣的直接用现成的就好,下面是提取像素值的具体实现:

    protected void getImagePixels() {
     int w = image.getWidth();
     int h = image.getHeight();
     pixels = new byte[w*h*3];
     for (int i = 0; i < h; i++) {
     int stride = w * 3 * i;
     for (int j = 0; j < w; j++) {
      int p = image.getPixel(j, i);
      int step = j * 3;
      int offset = stride + step;
      // blue
      pixels[offset+0] = (byte) ((p & 0x0000FF) >> 0);
      // green
      pixels[offset+1] = (byte) ((p & 0x00FF00) >> 8);
      // red
      pixels[offset+2] = (byte) ((p & 0xFF0000) >> 16); 
     }
     }
    }
    

    GIF 文件头(Header) 
    文件头部分总共 6 个字节,包括:GIF 署名和版本号,GIF 署名由 3 个字符”GIF”组成,共 3 个字节,版本号也是由 3 个字节组成,可以为”87a”或”89a”(分别为 1987 年和 1989 年版本),实现代码如下:

    // 写入文件头
    protected void writeHeader() throws IOException {
     writeString("GIF89a");
    }
    protected void writeString(String s) throws IOException {
     for (int i = 0; i < s.length(); i++) {
     out.write((byte) s.charAt(i));
     }
    }
    

    逻辑屏幕标识符(Logical Screen Descriptor) 
    文件头的后面是逻辑屏幕标识符(Logical Screen Descriptor),这一部分由 7 个字节组成,定义了 GIF 图象的大小、颜色深度、背景色以及有无全局颜色列表和颜色列表的索引数。实现代码如下:

    // 写入逻辑屏幕标识符

    protected void writeLSD() throws IOException {
     writeShort(width); // 写入图像宽度
     writeShort(height); // 写入图像高度
     out.write((0x80 | // 全局颜色列表标志置 1
        0x70 | // 确定图象的颜色深度(7+1=8)
        0x00 | // 全局颜色列表分类排列置为 0
        0x07)); // 颜色列表的索引数(2的7+1次方)
     out.write(0); // 背景颜色(在全局颜色列表中的索引)
     out.write(0); // 像素宽高比默认 1:1
    }
    protected void writeShort(int value) throws IOException {
     out.write(value & 0xff);
     out.write((value >> 8) & 0xff);
    }
    

    逻辑屏幕标识符部分结构稍微复杂些,如果不知道每一位代表什么意思可以参考:GIF图形文件格式文档 中的逻辑屏幕标识符部分。 
    全局颜色列表(Global Color Table) 
    全局颜色列表必须紧跟在逻辑屏幕标识符后面,每个颜色列表索引条目由三个字节组成,按R、G、B的顺序排列,具体生成颜色表的实现可以看源码部分,由于生成过程比较复杂,这里就不贴颜色表生成的代码了,下面是写入颜色表的代码:

    / 写入颜色表
    protected void writePalette() throws IOException {
     out.write(colorTab, 0, colorTab.length);
     int n = (3 * 256) - colorTab.length;
     for (int i = 0; i < n; i++) {
     out.write(0);
     }
    

    图形控制扩展(Graphic Control Extension) 
    这一部分是可选的,89a 版本才支持,可以放在一个图象块(包括图象标识符、局部颜色列表和图象数据)或文本扩展块的前面,用来控制跟在它后面的第一个图象(或文本)的渲染( Render )形式,下面实现代码:

    protected void writeGraphicCtrlExt() throws IOException {
     out.write(0x21); // 扩展块标识,固定值 0x21
     out.write(0xf9); // 图形控制扩展标签,固定值 0xf9
     out.write(4); // 块大小,固定值 4
     out.write(0 | // 1:3 保留位
       0 | // 4:6 不使用处置方法
       0 | // 7 用户输入标志置 0
       0); // 8 透明色标志置 0
     writeShort(delay); // 延迟时间
     out.write(0);  // 透明色索引值
     out.write(0);  // 块终结器,固定值 0
    }
    

    图象标识符(Image Descriptor) 
    一个 GIF 文件内可以包含多幅图象,一幅图象结束之后紧接着下是一幅图象的标识符,图象标识符以 0x2C(‘,’)字符开始,定义紧接着它的图象的性质,包括图象相对于逻辑屏幕边界的偏移量、图象大小以及有无局部颜色列表和颜色列表大小,由10个字节组成,下面是实现代码:

    protected void writeImageDesc() throws IOException {
     out.write(0x2c); // 图象标识符开始,固定值为 0x2c
     writeShort(0);  // x 方向偏移
     writeShort(0);  // y 方向偏移
     writeShort(width); // 图像宽度
     writeShort(height); // 图像高度
     out.write((
      0x80 |  // 局部颜色列表标志置 1
      0x00 |
      0x00 |
      0x07));  // 局部颜色列表的索引数(2的7+1次方)
    }
    

    图象数据(Image Data) 
    GIF 图象数据使用了 LZW 压缩算法,大大减小了图象数据的大小,具体的 LZW 压缩算法可以Google一下,下面是图像数据的写入实现:

    protected void writePixels() throws IOException {
     LZWEncoder encoder = new LZWEncoder(
      width, height, indexedPixels, colorDepth);
     encoder.encode(out);
    }
    

    文件终结器(Trailer) 
    这一部分只有一个字节,标识一个GIF文件结束,固定值为 0x3B,实现代码:

    public void finish() throws IOException {
     out.write(0x3b);
     out.flush();
     out.close();
    }
    

    总结 
    到目前为止,将 MP4 文件转换为 GIF 文件的实现过程基本完成,如果需要对 GIF 文件进行裁剪、添加水印等处理的话,可以在 Bitmap 序列写入 GIF 之前, Bitmap 进行相应的处理即可

    方案二思路:

    编译so文件过程:

    编译最后产生so,会自动生成一个libs目录:

    点击进入libs目录,可以发现一个是arm平台的so文件夹,一个是x86平台的so文件夹:

    随便点击一个,进入,就是一些so:

    体验 apk

    下载地址:链接: https://pan.baidu.com/s/1skR35nB 密码: 2wb3

    【相关推荐】

    我的其他Android Multimedia框架总结系列目录如下,点击目录可直接跳转:

    [[已推送]Android Multimedia框架总结(一)MediaPlayer介绍之状态图及生命周期]
    [[已推送]Android Multimedia框架总结(二)MediaPlayer框架及播放网络视频案例]
    [[已推送]Android Multimedia框架总结(三)MediaPlayer中创建到setDataSource过程]
    [[已推送]Android Multimedia框架总结(四)MediaPlayer从Java层到C++层类关系及prepare及之后其他过程]
    [[已推送]Android Multimedia框架总结(五)多媒体基础概念]
    [[已推送]Android Multimedia框架总结(六)C++中MediaPlayer的C/S架构]
    [[已推送]Android Multimedia框架总结(七)C++中MediaPlayer的C/S架构补充及MediaService介绍]
    [[已推送]Android Multimedia框架总结(八)Stagefright框架之AwesomePlayer及数据解析器]
    [[已推送]Android Multimedia框架总结(九)Stagefright框架之数据处理及到OMXCodec过程]
    [[已推送]Android Multimedia框架总结(十)Stagefright框架之音视频输出过程]
    [[已推送]Android Multimedia框架总结(十一)CodeC部分之AwesomePlayer到OMX服务]
    [[已推送]Android Multimedia框架总结(十二)CodeC部分之OMXCodec与OMX事件回调流程][[已推送]Android Multimedia框架总结(十三)CodeC部分之OpenMAX框架初识及接口与适配层实现]
    [[已推送]Android Multimedia框架总结(十四)Camera框架初识及自定义相机案例]
    [[已推送]Android Multimedia框架总结(十五)Camera框架之Camera2补充]
    [[已推送]Android Multimedia框架总结(十六)Camera2框架之openCamera及session过程]
    [[已推送]Android Multimedia框架总结(十七)音频开发基础知识]
    [[已推送]Android Multimedia框架总结(十八)Camera2框架从Java层到C++层类关系]
    [[已推送]Android Multimedia框架总结(二十)MediaCodec状态图及Codec与输入/输出Buffer过程(附实例)]
    [[已推送]Android Multimedia框架总结(二十一)MediaCodec中创建到start过程(到jni部分)]
    [[已推送]Android Multimedia框架总结(二十三)MediaCodec补充及MediaMuxer引入(附案例)]

    第一时间获得博客更新提醒,以及更多android干货,源码分析,欢迎关注我的微信公众号,扫一扫下方二维码或者长按识别二维码,即可关注。

    展开全文
  • 屏幕录制工具 Gif

    2017-08-07 11:17:31
    屏幕录制工具 Gif.rar
  • 屏幕录制GIF

    2018-05-31 18:29:05
    它可以直接从你电脑所在的屏幕上的任何区域进行操作和录制录制结束后可以将你做录制到的画面进行编辑,然后将你所录制到的画面保存为GIF图像。当然在录制开始之前你们可以去设置你们所想要录制的画面、录制的缩放...
  • 用于将指定屏幕的范围录制成gif,有预览和生成功能。对于写博客帮助很大
  • 功能:屏幕录制转换成gif,可录制鼠标点击动作,简单易用,简单易用,直接安装即可使用,轻量化的工具,屏幕录制转换成gif
  • 前言GIF可以把连续的图片变成动画,可以给好的把东西分享给别人观看,本篇主要记录和分享自己在...一、Mac 屏幕录制GIF 开始录制 大家可能没有留意过,QQ其实就已经有了录屏这项功能,它和截图功能是在一起的,(...
  • 好用的屏幕录制软件 屏幕录制软件转GIF图强烈建议使用ScreenToGif,工具小,简洁而又实用,而且没有广告,完全免费
  • 屏幕录制gif

    2016-09-19 12:24:03
    LICEcap简洁易用的动画屏幕录制软件,0积分下载。LICEcap 捕捉屏幕的区域并保存为gif动画(便于网络发布)或lcf格式。 功能特点: 录制为 .GIF 或 .LCF。 录制过程中,可移动捕捉框,从而改变录制范围。 暂停/重新...
  • 一、前言 JavaCV第9章开始到第12章,我们主要对屏幕录制和gif/png动态...本章是为了演示如何使用JavaCV来作桌面屏幕画面录制gif或者apng等动态图片,再本章基础上修改即可做到MacOS\linux\安卓的桌面屏幕录制成gif,

空空如也

空空如也

1 2 3 4 5 ... 20
收藏数 6,437
精华内容 2,574
关键字:

屏幕录制成gif