精华内容
下载资源
问答
  • 帧缓存介绍

    千次阅读 2009-12-15 21:04:00
    帧缓存介绍 在opengl里经常看到帧缓存这个名词,可以是opengl的核心的吧。平时写程序由于只与它的子集颜色缓存,深度缓存,模板缓存,累积缓存打交道,很少想它们的父类的帧缓存的定义。今天在看gpu的流水线时,讲到...
     
    

    在opengl里经常看到帧缓存这个名词,可以是opengl的核心的吧。平时写程序由于只与它的子集颜色缓存,深度缓存,模板缓存,累积缓存打交道,很少想它们的父类的帧缓存的定义。
    今天在看gpu的流水线时,讲到片元的各种操作,突然想到自己对这个一直不是特别明白。
    在渲染过程中,图形加速器一般都有一个预先分配好的内存区域来维护显示列表内容(译者:注意,不一定是主内存)。它由显示内存和脱屏内存组成。随着OpenGL的渲染而改变内容的那一部分图形内存区域叫做帧缓存(frame buffer)。在窗口系统里,OpenGL通过帧缓存与窗口通信。窗口系统为OpenGL提供了一组工具来为窗口选择帧缓存特性,而这组工具,通常是系统相关的。

    一个支持OpenGL渲染的窗口 (即帧缓存) 可能包含以下的组合:

    · 至多4个颜色缓存

    · 一个深度缓存

    · 一个模板缓存

    · 一个积累缓存

    · 一个多重采样缓存

      为了能够执行双缓存构架,大多数图形硬件同时支持前后缓存。这将允许应用程序在显示前缓存(可见的)的时候渲染到后缓存(离屏缓存)。当渲染结束的时候,这两个缓存进行交换,以便已经完成渲染的缓存像前缓存一样进行显示,这样渲染就能在后缓存重新开始了。一旦使用双缓存,在绘制过程当中用户将不能看到图像。这种技术通常被用来实现实时交互的平滑动画。

      如果为左眼和右眼各实现一个颜色缓存的话,那么就可以支持立体视觉效果了。双缓存技术由前后缓存来支持。因此一个双缓存的立体视觉将会有4各颜色缓存:前左,前右,后左,后右。一个普通的(非立体的)双缓存窗口将会仅仅有前后两个缓存。一个单缓存的窗口将会只有一个缓存。

      如果绘制3D对象时需要剔除隐藏表面的话,深度缓存是必要的。这个缓存在每个象素上存储了显示对象的深度值。当绘制附加对象的时候,会在每个象素上进行深度比较,这样就能决定新的对象是否可见。

      模板缓存用来进行复杂的掩模(masking)操作。一个复杂的形状可以存储在模板缓存里,然后绘制子序列操作可以使用模板缓存里的内容来决定是否更新象素。

      积累缓存是一个颜色缓存,不过典型地它有比颜色缓存更高的精度。这就允许一些图像通过积累产生一些合成的图像。比如说一个作用就是可以在积累缓存里对一个对象随着他的运动绘制一些帧数。在积累缓存中的象素除以帧数以后,结果图像就展现出了运动模糊效果。相似的技巧也可以用来模拟景深效果以及高质量的全屏抗锯齿。

      而通常的,当一个对象被绘制的时候,对于某个图元是否影像屏幕上的象素,会做一个单独的决议。多重采样缓存正是这样一个缓存,它允许每个渲染的对象在象素内被采样多次,以进行高质量的全屏抗锯齿,而不必对这个对象渲染多次。每个象素内的采样包括:颜色,深度,模板信息。每个象素采样的次数当然是必须的。当窗口包含多重采样缓存的时候,它将不回包括单独的深度或者是模板缓存。随着对象的渲染,颜色样本会被组合生成一个单一的颜色值,然后这个颜色值被传递,并写入到颜色缓存里。因为他们包括窗口中每个象素的多个颜色、深度以及模板样本(通常是4,8或者是16),因此多重采样缓存会消耗相当数量的离屏缓存。

    展开全文
  • OpenGL帧缓存对象(FBO)

    千次阅读 2016-04-12 21:09:10
    OpenGL帧缓存对象(FBO:Frame Buffer Object) 参考地址:http://blog.csdn.net/dreamcs/article/details/7691690 帧缓存(Frame buffer) 帧缓存是屏幕所显示画面的一个直接映象,又称为位映射图 (Bit Map) 或光栅。...
    OpenGL帧缓存对象(FBO:Frame Buffer Object)


    帧缓存(Frame buffer)

    帧缓存是屏幕所显示画面的一个直接映象,又称为位映射图 (Bit Map) 或光栅。帧缓存的每一存储单元对应屏幕上的一个像素,整个帧缓存对应一帧图像。

    图形程序一个重要的目标,就是在屏幕上绘制图像(或者绘制到离屏的一处缓存中)。帧缓存(通常也就是屏幕)是由矩形的像素数组组成的,每个像素都可以在图像对应的点上显示一小块方形的颜色值。经过光栅化阶段,也就是执行片元着色器之后,得到的数据还不是真正的像素,只是候选的片元。每个片元都包含与像素位置对应的坐标数据,以及颜色和深度的存储值。通常来说,像素(x,y)填充的区域是以x为左侧,x+1为右侧,y为底部,而y+1为顶部的一处矩形区域。

    一个支持OpenGL渲染的窗口 (即帧缓存) 可能包含以下的组合:
    至多4个颜色缓存,一个深度缓存,一个模板缓存,一个积累缓存,一个多重采样缓存。

    OpenGL给了我们自己定义帧缓存的自由,我们可以选择性的定义自己的颜色缓冲、深度和模板缓冲。我们目前所做的渲染操作都是是在默认的帧缓冲之上进行的。当你创建了你的窗口的时候默认帧缓冲就被创建和配置好了(GLFW为我们做了这件事)。通过创建我们自己的帧缓冲我们能够获得一种额外的渲染方式。

    创建一个帧缓存

    我们可以使用一个叫做glGenFramebuffers的函数来创建一个帧缓冲对象(简称FBO):

    GLuint fbo;
    glGenFramebuffers(1, &fbo);

    这种对象的创建和使用的方式与之前见到的差不多。先创建一个帧缓冲对象,把它绑定到当前帧缓冲,做一些操作,然后解绑帧缓冲。我们使用glBindFramebuffer来绑定帧缓冲:

    glBindFramebuffer(GL_FRAMEBUFFER, fbo);

    绑定到GL_FRAMEBUFFER目标后,接下来所有的读、写帧缓冲的操作都会影响到当前绑定的帧缓冲。也可以使用GL_READ_FRAMEBUFFER或GL_DRAW_FRAMEBUFFER,把帧缓冲分开绑定到读或写目标上。

    建构一个完整的帧缓冲必须满足以下条件:

    • 我们必须往里面加入至少一个附件(颜色、深度、模板缓冲)。
    • 其中至少有一个是颜色附件。
    • 所有的附件都应该是已经完全做好的(已经存储在内存之中)。
    • 每个缓冲都应该有同样数目的样本。

    我们需要为帧缓冲创建一些附件,还需要把这些附件附加到帧缓冲上。然后使用下面方法检查是否完成:

    if(glCheckFramebufferStatus(GL_FRAMEBUFFER) == GL_FRAMEBUFFER_COMPLETE)

    后续所有渲染操作将渲染到当前绑定的帧缓存的附加缓存中,由于我们的帧缓冲不是默认的帧缓存,渲染命令对窗口的视频输出不会产生任何影响。出于这个原因,它被称为离屏渲染(off-screen rendering),就是渲染到一个另外的缓存中。

    如果要使渲染操作对窗口产生影响,要重新绑定0来使默认帧缓冲激活:

    glBindFramebuffer(GL_FRAMEBUFFER, 0);

    当做完所有帧缓冲操作,要删除帧缓冲对象:

    glDeleteFramebuffers(1, &fbo);

    在执行完成检测前,我们先把一个或更多的附件附加到帧缓冲上。一个附件就是一个内存地址,这个内存地址里面包含一个为帧缓冲准备的缓冲,它可以是个图像。当创建一个附件的时候我们有两种方式可以采用:纹理或渲染缓冲(renderbuffer)对象。

    纹理附件(Texture attachments)

    当把一个纹理附件加到帧缓冲上的时候,所有渲染命令会写入到纹理上,就像它是一个普通的颜色、深度或者模板缓冲一样。使用纹理的好处是,所有渲染操作的结果都会被储存为一个纹理图像,这样我们就可以简单的在着色器中使用了。

    为帧缓存创建一个纹理和创建普通纹理差不多:

    GLuint texture;
    glGenTextures(1, &texture);
    glBindTexture(GL_TEXTURE_2D, texture);
    
    glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, 800, 600, 0, GL_RGB, GL_UNSIGNED_BYTE, NULL);
    
    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);

    主要的区别是我们把纹理的维度设置为屏幕大小(尽管不是必须的),我们还传递NULL作为纹理的data参数。对于这个纹理,我们只分配内存,而不去填充它。纹理填充会在渲染到帧缓冲的时候去做。同样,要注意,我们不用关心环绕方式或者Mipmap,因为在大多数时候都不会需要它们的。

    如果你打算把整个屏幕渲染到一个或大或小的纹理上,你需要用新的纹理的尺寸再次调用glViewport(在渲染到你的帧缓冲前),否则只有一小部分纹理或屏幕能够绘制到纹理上。

    现在我们已经创建了一个纹理,最后一件要做的事情是把它附加到帧缓冲上:

    glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0,GL_TEXTURE_2D, texture, 0);

    glFramebufferTexture2D 函数的参数:

    • target:我们所创建的帧缓冲类型的目标(绘制、读取或两者都有)。
    • attachment:我们所附加的附件的类型。现在我们附加的是一个颜色附件。需要注意,最后的那个0是暗示我们可以附加1个以上颜色的附件。
    • textarget:你希望附加的纹理类型。
    • texture:附加的实际纹理。
    • level:Mipmap level。我们设置为0。

    除颜色附件以外,我们还可以附加一个深度和一个模板纹理到帧缓冲对象上。若要附加深度缓冲类型,使用GL_DEPTH_ATTACHMENT设置附件类型。若要附加模板缓冲,要使用 GL_STENCIL_ATTACHMENT设置附加类型,同时把glTexImage2D中纹理格式指定为 GL_STENCIL_INDEX。

    也可以同时附加一个深度缓冲和一个模板缓冲为一个单独的纹理。这样纹理的每32位数值就包含了24位的深度信息和8位的模板信息。可以使用GL_DEPTH_STENCIL_ATTACHMENT类型设置,下面是一个附加了深度和模板缓冲为单一纹理的例子:

    glTexImage2D( GL_TEXTURE_2D, 0, GL_DEPTH24_STENCIL8, 800, 600, 0, GL_DEPTH_STENCIL, GL_UNSIGNED_INT_24_8, NULL );
    glFramebufferTexture2D(GL_FRAMEBUFFER, GL_DEPTH_STENCIL_ATTACHMENT, GL_TEXTURE_2D, texture, 0);
    渲染缓冲对象附件(Renderbuffer object attachments)

    帧缓存的附件方式除了纹理,还有渲染缓冲对象(Renderbuffer objects)。和纹理一样,渲染缓冲对象也是一个缓冲,它可以是一堆字节、整数、像素或者其他东西。渲染缓冲对象的一大优点是,它以OpenGL原生渲染格式储存它的数据,因此在离屏渲染到帧缓冲的时候,这些数据就相当于被优化过的了,在写入或把它们的数据简单地到其他缓冲的时候非常快。

    渲染缓冲对象将所有渲染数据直接储存到它们的缓冲里,而不会进行针对特定纹理格式的任何转换,这样它们就成了一种快速可写的存储介质了。然而,渲染缓冲对象通常是只写的,不能修改它们(就像获取纹理,不能写入纹理一样)。可以用glReadPixels函数去读取,函数返回一个当前绑定的帧缓冲的特定像素区域,而不是直接返回附件本身。

    创建一个渲染缓冲对象和创建帧缓冲代码差不多:

    GLuint rbo;
    glGenRenderbuffers(1, &rbo);

    相似地,把渲染缓冲对象绑定,这样所有后续渲染缓冲操作都会影响到当前的渲染缓冲对象:

    glBindRenderbuffer(GL_RENDERBUFFER, rbo);

    由于渲染缓冲对象通常是只写的,它们经常作为深度和模板附件来使用。因为我们需要把深度值和模板值提供给测试,但不需要对这些值采样,所以深度和模板缓冲对象是完全符合的。当我们不去从这些缓冲中采样的时候,渲染缓冲对象通常很合适,因为它们等于是被优化过的。

    调用glRenderbufferStorage函数可以创建一个深度和模板渲染缓冲对象,我们选择GL_DEPTH24_STENCIL8作为内部格式:

    glRenderbufferStorage(GL_RENDERBUFFER, GL_DEPTH24_STENCIL8, 800, 600);

    最后一件还要做的事情是把帧缓冲对象附加上:

    glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_DEPTH_STENCIL_ATTACHMENT, GL_RENDERBUFFER, rbo);
    • 比较
      在帧缓冲项目中,渲染缓冲对象可以提供一些优化,但更重要的是知道何时使用渲染缓冲对象,何时使用纹理。通常的规则是,如果你永远都不需要从特定的缓冲中进行采样,渲染缓冲对象对特定缓冲是更明智的选择。如果哪天需要从比如颜色或深度值这样的特定缓冲采样数据的话,你最好还是使用纹理附件。从执行效率角度考虑,它不会对效率有太大影响。
    渲染到纹理

    现在我们知道了一些帧缓冲工作原理,开始尝试使用它们。我们把场景渲染到一个颜色纹理上,这个纹理附加到一个我们创建的帧缓冲上,然后把这个纹理绘制到一个铺满屏幕的四边形上。输出的图像看似和没用帧缓冲一样,但其实是直接打印到了一个单独的四边形上面。为什么这很有用呢?下一部分我们会看到原因。

    我们先来创建帧缓存,具体思路是:
    先创建帧缓存,然后创建一个颜色纹理附件用于绘制,再创建一个深度和模板 渲染缓存对象用于深度测试(本例先不使用模板测试),还要把它们都附加到帧缓存上。

    第一件要做的事情是创建一个帧缓冲对象,并绑定它,这比较明了:

    GLuint framebuffer;
    glGenFramebuffers(1, &framebuffer);
    glBindFramebuffer(GL_FRAMEBUFFER, framebuffer);

    下一步我们创建一个纹理图像,这是我们将要附加到帧缓冲的颜色附件。我们把纹理的尺寸设置为窗口的宽度和高度,并保持数据未初始化:

    // Generate texture
    GLuint texColorBuffer;
    glGenTextures(1, &texColorBuffer);
    glBindTexture(GL_TEXTURE_2D, texColorBuffer);
    glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, 800, 600, 0, GL_RGB, GL_UNSIGNED_BYTE, NULL);
    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR );
    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
    glBindTexture(GL_TEXTURE_2D, 0);
    
    // 把颜色纹理附加到帧缓存上
    glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, texColorBuffer, 0);

    接下来创建一个渲染缓冲对象来进行深度测试和模板测试。记住,当你不打算从指定缓冲采样的的时候,渲染缓冲对象是不错的选择。我们把它设置为GL_DEPTH24_STENCIL8,对于我们的目的来说这个精确度已经足够了。

    GLuint rbo;
    glGenRenderbuffers(1, &rbo);
    glBindRenderbuffer(GL_RENDERBUFFER, rbo);
    glRenderbufferStorage(GL_RENDERBUFFER, GL_DEPTH24_STENCIL8, 800, 600);  
    glBindRenderbuffer(GL_RENDERBUFFER, 0);
    
    // 把渲染缓冲对象附加到 帧缓冲
    glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_DEPTH_STENCIL_ATTACHMENT, GL_RENDERBUFFER, rbo);

    然后我们检查帧缓冲是否完成了:

    if(glCheckFramebufferStatus(GL_FRAMEBUFFER) != GL_FRAMEBUFFER_COMPLETE){
        cout << "ERROR::FRAMEBUFFER:: Framebuffer is not complete!" << endl;
    }
    // 解绑帧缓冲,确保不会意外渲染到错误的帧缓冲上。
    glBindFramebuffer(GL_FRAMEBUFFER, 0);

    现在完成帧缓存了,要做的就是渲染到帧缓存上。具体流程如下:

    1. 绑定我们创建的帧缓存来激活它,开启深度测试。
    2. 绘制场景内容。此时都绘制到了帧缓存的纹理上。
    3. 再绑定默认的帧缓存来激活它。
    4. 使用上面的纹理来绘制四边形,同时关闭深度测试(因为绘制一个四边形不需要深度测试)。

    最后,我们能看到场景内容,结果和之前不使用自定义的帧缓存是一样的。然而这有什么好处呢?那就是场景中的任何像素已经被当作一个纹理图像了,我们可以在片段着色器中对其创建一些有意思的效果。所有这些有意思的效果统称为后处理特效。



    文/fan2b(简书作者)
    原文链接:http://www.jianshu.com/p/7a4c8cd4587e
    著作权归作者所有,转载请联系作者获得授权,并标注“简书作者”。
    展开全文
  • 其中,将数据帧存储到帧缓存器中的原理已经介绍过了。 那么,本小节,我们重点分析一下,写流控的原理; 也就是说, 我们要分析的场景是:   当创建好的数据帧是不是可以不加限制的写入帧缓存器里? 假设,这个...

    上一小节我们已经知道如何创建数据帧,然后对数据帧进行写流控,最后将数据帧存储到帧缓存器中;

    其中,将数据帧存储到帧缓存器中的原理已经介绍过了。

    那么,本小节,我们重点分析一下,写流控的原理;

    也就是说,

    我们要分析的场景是:

      当创建好的数据帧是不是可以不加限制的写入帧缓存器里?

    假设,这个功能让我们自己实现的话,可参考的方案是:
    • 暂时暂停数据帧的写入,等满足条件时,再允许数据帧写入
    • 降低写入帧缓存器的频率

    1、分析入口

    grpc-go/internal/transport/http2_client.go文件中的Write方法里:

    1.func (t *http2Client) Write(s *Stream, hdr []byte, data []byte,
    展开全文
  • Android 三大图片缓存原理、特性对比

    千次阅读 2016-09-13 15:43:48
    Android 三大图片缓存原理、特性对比

    这是我在 MDCC 上分享的内容(略微改动),也是源码解析第一期发布时介绍的源码解析后续会慢慢做的事。

     

    从总体设计和原理上对几个图片缓存进行对比,没用到他们的朋友也可以了解他们在某些特性上的实现。

     

    上篇关于选择开源项目的好处及如何选择开源项目可见:开源项目使用及选型

     

    一. 四大图片缓存基本信息


    Universal ImageLoader 是很早开源的图片缓存,在早期被很多应用使用。

     

    Picasso 是 Square 开源的项目,且他的主导者是 JakeWharton,所以广为人知。

     

    Glide 是 Google 员工的开源项目,被一些 Google App 使用,在去年的 Google I/O 上被推荐,不过目前国内资料不多。

     

    Fresco 是 Facebook 在今年上半年开源的图片缓存,主要特点包括:
    (1) 两个内存缓存加上 Native 缓存构成了三级缓存

     

    (2) 支持流式,可以类似网页上模糊渐进式显示图片

     

    (3) 对多帧动画图片支持更好,如 Gif、WebP

     

    鉴于 Fresco 还没发布正式的 1.0 版本,同时一直没太多时间熟悉 Fresco 源码,后面对比不包括 Fresco,以后有时间再加入对比。

     

    更多图片缓存库可见:Android 图片缓存库

     

    二、基本概念

    在正式对比前,先了解几个图片缓存通用的概念:
    (1) RequestManager:请求生成和管理模块

     

    (2) Engine:引擎部分,负责创建任务(获取数据),并调度执行

     

    (3) GetDataInterface:数据获取接口,负责从各个数据源获取数据。
    比如 MemoryCache 从内存缓存获取数据、DiskCache 从本地缓存获取数据,下载器从网络获取数据等。

     

    (4) Displayer:资源(图片)显示器,用于显示或操作资源。
    比如 ImageView,这几个图片缓存都不仅仅支持 ImageView,同时支持其他 View 以及虚拟的 Displayer 概念。

     

    (5) Processor 资源(图片)处理器
    负责处理资源,比如旋转、压缩、截取等。

     

    以上概念的称呼在不同图片缓存中可能不同,比如 Displayer 在 ImageLoader 中叫做 ImageAware,在 Picasso 和 Glide 中叫做 Target。

     

    三、共同优点

    1. 使用简单
    都可以通过一句代码可实现图片获取和显示。

     

    2. 可配置度高,自适应程度高
    图片缓存的下载器(重试机制)、解码器、显示器、处理器、内存缓存、本地缓存、线程池、缓存算法等大都可轻松配置。

     

    自适应程度高,根据系统性能初始化缓存配置、系统信息变更后动态调整策略。
    比如根据 CPU 核数确定最大并发数,根据可用内存确定内存缓存大小,网络状态变化时调整最大并发数等。

     

    3. 多级缓存
    都至少有两级缓存、提高图片加载速度。

     

    4. 支持多种数据源
    支持多种数据源,网络、本地、资源、Assets 等

     

    5. 支持多种 Displayer
    不仅仅支持 ImageView,同时支持其他 View 以及虚拟的 Displayer 概念。

     

    其他小的共同点包括支持动画、支持 transform 处理、获取 EXIF 信息等。

     

    四、ImageLoader 设计及优点

    1. 总体设计及流程

    上面是 ImageLoader 的总体设计图。整个库分为 ImageLoaderEngine,Cache 及 ImageDownloader,ImageDecoder,BitmapDisplayer,BitmapProcessor 五大模块,其中 Cache 分为 MemoryCache 和 DiskCache 两部分。

     

    简单的讲就是 ImageLoader 收到加载及显示图片的任务,并将它交给 ImageLoaderEngine,ImageLoaderEngine 分发任务到具体线程池去执行,任务通过 Cache 及 ImageDownloader 获取图片,中间可能经过 BitmapProcessor 和 ImageDecoder 处理,最终转换为Bitmap 交给 BitmapDisplayer 在 ImageAware 中显示。

     

    2. ImageLoader 优点

    (1) 支持下载进度监听

     

    (2) 可以在 View 滚动中暂停图片加载
    通过 PauseOnScrollListener 接口可以在 View 滚动中暂停图片加载。

     

    (3) 默认实现多种内存缓存算法 这几个图片缓存都可以配置缓存算法,不过 ImageLoader 默认实现了较多缓存算法,如 Size 最大先删除、使用最少先删除、最近最少使用、先进先删除、时间最长先删除等。

     

    (4) 支持本地缓存文件名规则定义

     

    五、Picasso 设计及优点

    1. 总体设计及流程

    上面是 Picasso 的总体设计图。整个库分为 Dispatcher,RequestHandler 及 Downloader,PicassoDrawable 等模块。

     

    Dispatcher 负责分发和处理 Action,包括提交、暂停、继续、取消、网络状态变化、重试等等。

     

    简单的讲就是 Picasso 收到加载及显示图片的任务,创建 Request 并将它交给 Dispatcher,Dispatcher 分发任务到具体 RequestHandler,任务通过 MemoryCache 及 Handler(数据获取接口) 获取图片,图片获取成功后通过 PicassoDrawable 显示到 Target 中。

     

    需要注意的是上面 Data 的 File system 部分,Picasso 没有自定义本地缓存的接口,默认使用 http 的本地缓存,API 9 以上使用 okhttp,以下使用 Urlconnection,所以如果需要自定义本地缓存就需要重定义 Downloader。

     

    2. Picasso 优点

    (1) 自带统计监控功能
    支持图片缓存使用的监控,包括缓存命中率、已使用内存大小、节省的流量等。

     

    (2) 支持优先级处理
    每次任务调度前会选择优先级高的任务,比如 App 页面中 Banner 的优先级高于 Icon 时就很适用。

     

    (3) 支持延迟到图片尺寸计算完成加载

     

    (4) 支持飞行模式、并发线程数根据网络类型而变
    手机切换到飞行模式或网络类型变换时会自动调整线程池最大并发数,比如 wifi 最大并发为 4, 4g 为 3,3g 为 2。
    这里 Picasso 根据网络类型来决定最大并发数,而不是 CPU 核数。

     

    (5) “无”本地缓存
    无”本地缓存,不是说没有本地缓存,而是 Picasso 自己没有实现,交给了 Square 的另外一个网络库 okhttp 去实现,这样的好处是可以通过请求 Response Header 中的 Cache-Control 及 Expired 控制图片的过期时间。

     

    六、Glide 设计及优点

    1. 总体设计及流程

    上面是 Glide 的总体设计图。整个库分为 RequestManager(请求管理器),Engine(数据获取引擎)、 Fetcher(数据获取器)、MemoryCache(内存缓存)、DiskLRUCache、Transformation(图片处理)、Encoder(本地缓存存储)、Registry(图片类型及解析器配置)、Target(目标) 等模块。

     

    简单的讲就是 Glide 收到加载及显示资源的任务,创建 Request 并将它交给RequestManager,Request 启动 Engine 去数据源获取资源(通过 Fetcher ),获取到后 Transformation 处理后交给 Target。

     

    Glide 依赖于 DiskLRUCache、GifDecoder 等开源库去完成本地缓存和 Gif 图片解码工作。

     

    2. Glide 优点

    (1) 图片缓存->媒体缓存
    Glide 不仅是一个图片缓存,它支持 Gif、WebP、缩略图。甚至是 Video,所以更该当做一个媒体缓存。

     

    (2) 支持优先级处理

     

    (3) 与 Activity/Fragment 生命周期一致,支持 trimMemory
    Glide 对每个 context 都保持一个 RequestManager,通过 FragmentTransaction 保持与 Activity/Fragment 生命周期一致,并且有对应的 trimMemory 接口实现可供调用。

     

    (4) 支持 okhttp、Volley
    Glide 默认通过 UrlConnection 获取数据,可以配合 okhttp 或是 Volley 使用。实际 ImageLoader、Picasso 也都支持 okhttp、Volley。

     

    (5) 内存友好
    ① Glide 的内存缓存有个 active 的设计
    从内存缓存中取数据时,不像一般的实现用 get,而是用 remove,再将这个缓存数据放到一个 value 为软引用的 activeResources map 中,并计数引用数,在图片加载完成后进行判断,如果引用计数为空则回收掉。

     

    ② 内存缓存更小图片
    Glide 以 url、view_width、view_height、屏幕的分辨率等做为联合 key,将处理后的图片缓存在内存缓存中,而不是原始图片以节省大小

     

    ③ 与 Activity/Fragment 生命周期一致,支持 trimMemory

     

    ④ 图片默认使用默认 RGB_565 而不是 ARGB_888
    虽然清晰度差些,但图片更小,也可配置到 ARGB_888。

     

    其他:Glide 可以通过 signature 或不使用本地缓存支持 url 过期

     

    七、汇总


    三者总体上来说,ImageLoader 的功能以及代理容易理解长度都一般。

     

    Picasso 代码虽然只在一个包下,没有严格的包区分,但代码简单、逻辑清晰,一两个小时就能叫深入的了解完。

     

    Glide 功能强大,但代码量大、流转复杂。在较深掌握的情况下才推荐使用,免得出了问题难以下手解决。

     

    更多图片缓存库可见:Android 图片缓存库

    展开全文
  • 缓存
  • 四大图片缓存基本信息 Universal ImageLoader 是很早开源的图片缓存,在早期被很多应用使用。   Picasso 是 Square 开源的项目,且他的主导者是 JakeWharton,所以广为人知。   Glide 是 Google 员工的...
  • 从总体设计和原理上对几个图片缓存进行对比,没用到他们的朋友也可以了解他们在某些特性上的实现。   上篇关于选择开源项目的好处及如何选择开源项目可见:开源项目使用及选型。   一. 四大图片缓存基本信息 ...
  • android 三大图片缓存原理、特性对比

    千次阅读 2015-10-23 16:06:52
    转载自csdn首页移动开发一 四大图片缓存的基本信息 Universal ImageLoader 是很早开源的图片缓存,在早期被很多应用使用。Picasso 是 Square 开源的项目,且他的主导者是 JakeWharton,所以广为人知。Glide 是 ...
  • 【原创】IP摄像头技术纵览(三)—图像数据在帧缓存设备(framebuffer)上的显示本文属于《IP摄像头技术纵览》系列文章之一:Author: chad Mail: linczone@163.com 本文可以自由转载,但转载请务必注明出处以及本...
  • 1、加载Gif图片的时候如果最后一为透明的会出现闪烁的情况 2、Gilde使用的时候消耗内存比较严重,希望谨慎使用 Fresco的优点: 1、Freso的优点在于内存的管理,解决了图片占用内存自动释放的问题,减少了因为图片...
  • 为了能快速让用户看到题目,题库都存在阿里云持久型缓存数据库Redis上。 现场人员发出信息,通过接入方的AppServer,调用阿里云的OpenAPI,在直播视频流当前位置中插入若干SEI内容可由业务自定义。 播放...
  • 用rosbag录了一段数据,在rviz上...于是重新打开rviz,重新添加topic,这样不会缓存数据,然后又打开之前的.rviz配置,就不会缓存数据了。不知道原理是什么,作为暂时的解决方法吧。 还有一种方法,先放ba...
  • 动画中的关键动画的原理

    千次阅读 2019-03-03 02:20:07
    本文转载自博主”早上吃什么“《动画中的关键动画的原理》一文。 想一想如果制作动画,如果没有关键这种技术会是多么恐怖,如果动画帧率为25,即每秒要播放25张画面,假设现在要制作1秒的动画,那么就需要手动...
  • 从总体设计和原理上对几个图片缓存进行对比,没用到他们的朋友也可以了解他们在某些特性上的实现。 略掉前面关于选择开源项目的好处及如何选择开源项目的部分(回复"开源项目"查看),进入重点。 一. 四大...
  • 而我们的GPU则是负责对位图进行渲染,最后将渲染好的位图放到帧缓存区。由视频控制器在指定时间之前去帧缓冲区提取显示内容,通过显示屏显示出来。 举例说明 当我们创建一个UIView控件之后,它的显示部分由CALayer...
  •  间(Interframe)压缩的原理是:相邻几的数据有很大的相关性,或者说前后两信息变化很小的特点。也即连续的视频其相邻之间具有冗余信息,根据这一特性,压缩相邻之间的冗余量就可以进一步提高压缩量,...
  • 缓存区溢出攻击原理

    千次阅读 2014-04-15 07:47:43
    缓冲区溢出攻击是一种常见的攻击其攻击原理和相关知识见: http://blog.programfan.com/article.asp?id=30692  下面是小型的攻击演示程序,程序源代码如下: #include #include #include void callCmd(){ ...
  • H264编码原理以及IBP

    千次阅读 2016-11-03 22:58:30
    前言   H264是新一代的编码标准,以高压缩高质量和支持多种网络的流媒体传输著称,在编码...所以对于一段变化不大图像画面,我们可以先编码出一个完整的图像A,随后的B就不编码全部图像,只写入与A的差别,
  • H264 编码原理及IBP

    千次阅读 2016-05-31 12:02:50
    前言  H264是新一代的编码标准,以高压缩高质量和支持多种网络的流媒体传输著称,在编码方面...所以对于一段变化不大的图像画面,我们可以先编码出一个完整的图像A,随后的B就不用编码全部图像,只写入与A的差别
  • H264编码原理以及IPB

    千次阅读 2016-04-11 20:45:09
    前言   H264是新一代的编码标准,以高压缩高质量和支持多种网络的流媒体传输著称,在编码...所以对于一段变化不大图像画面,我们可以先编码出一个完整的图像A,随后的B就不编码全部图像,只写入与A的差别,
  • 由于直播推送端会存在于各种不同的网络环境下面:有线、无线、3G、4G、卫星信号等等,在这些网络条件下,如何做到能够做到灵活、低延时直播,我们这个时候就需要引入发送缓冲区和丢策略两种功能,保证推送的实时和...
  • 嵌入式 H.264编码原理以及IBP

    千次阅读 2013-12-02 14:50:15
    关键包含了显示需要的所有信息 所有的视频都至少包含一个关键,作为文件的第一个。其它的关键可用来改善视频的质量,不过它们也会增加文件大小。一般而言,每一秒视频至少需要使用 1 个关键。若使用...
  • 前言  H264是新一代的编码标准,以高压缩高质量和支持多种网络的流媒体传输著称,在...所以对于一段变化不大图像画面,我们可以先编码出一个完整的图像A,随后的B就不编码全部图像,只写入与A的差别,这样B
  • 一、关键帧缓存策略 典型的视频帧序列为IBBPBBPBBP…… 对于直播而言,为了减少直播的延时,通常在编码时不使用B帧。P帧B帧对于I帧都有直接或者间接的依赖关系,所以播放器要解码一个视频帧序列,并进行播放,必须...
  • SDH原理--2.SDH信号的结构

    千次阅读 2021-05-17 09:04:01
    SDH信号的结构和复用步骤 目标: 1.1 SDH信号——STM-N的结构 诀窍: 想一想: (1)信息净负荷(payload) 技术细节: (2)段开销(SOH) 技术细节: (3)管理单元指针(AU-PTR) 1.2 SDH的复用...
  • H.264编码原理以及IBP

    千次阅读 2015-04-10 19:05:12
    前言 -----------------------  H264是新一代的编码标准,以高压缩高质量和支持多种网络的流媒体传输著称,在编码方面,我理解的他的...所以对于一段变化不大图像画面,我们可以先编码出一个完整的图像A,随后的B
  • H264--1--编码原理以及IBP

    千次阅读 2016-12-21 08:25:12
    在H264中图像以序列为单位进行组织,一个序列是一段图像编码后的数据流,以I开始,到下一个I结束。  一个序列的第一个图像叫做 IDR 图像(立即刷新图像),IDR 图像都是 I 图像。H.264 引入 IDR 图像是为了...

空空如也

空空如也

1 2 3 4 5 ... 20
收藏数 39,722
精华内容 15,888
关键字:

帧缓存原理