【问题标题】:loading bpg images: compatible, simple and efficient techniques加载bpg图片:兼容、简单、高效的技术
【发布时间】:2015-02-19 13:48:11
【问题描述】:

最近有一些关于 Fabrice Bellard 的 BPG 图像格式 (http://bellard.org/bpg/) 的讨论,该格式(基于他网站上提供的演示)提供比 jpeg、webp 和其他一些更好的压缩。图像解码是在浏览器中用JS完成的,这意味着它可以立即使用,无需等待浏览器采用。总体而言,这似乎是一个好主意,用一些 CPU 时间换取更快的下载速度通常是一个可行的折衷方案。

used here 换出图像的技术是在 window.load 上迭代 document.images,找到 src 属性包含以“.bpg”结尾的 URL 的任何位置,并将其替换为画布。

然而,这绝对不是解决问题的唯一方法,我看到了这种技术的一些缺点,其中包括:a) 画布与图像没有完全相同的布局规则 - 例如在其上设置宽度属性意味着在 img 与画布上有所不同,b) 似乎至少在 Chrome 中,对于缩小的图像与画布的缩放方式是不同的。

一个更好的解决方案最好能满足这些要求:

  • 尽量不要在内存中复制不必要的图像数据(也不要不必要地使用比必要更多的 CPU - 与原生图像处理相比,在 JS 中解码已经需要很多)
  • 尽可能多地兼容浏览器
  • 使用 标签而不是 (不是必需的,但似乎更好)
  • 提供一种简单的方法,不仅可以处理加载文档时的图像,还可以处理稍后添加到文档中的图像(例如响应用户活动)
  • 仍然易于使用(bellard.org 上的现有技术当然很容易集成)
  • 编辑:使用网络工作者在不阻塞页面的情况下解码图像也是一个不错的方法。

想到的一些相关工具包括 data: 和 blob: urls。

任何人都有使用这种“更好”技术加载 BPG 的工作代码示例? (Fabrice 在他的示例中使用它的方式还不错,当然方法也有取舍,但我认为可能有更好的方法可以通用。)

【问题讨论】:

  • 我希望有人回答这个问题,我想补充一下:当前的 js 代码是 C 代码的一个端口——我们能想象原生 js 实现的性能/尺寸改进吗?
  • 关于<img>标签,生成data-url意味着将图片编码成浏览器支持的格式,然后用base64编码。虽然后者很容易,但前者在 javascript 中可能非常慢,例如从bpg_decode 提供的纯像素数据编码 PNG 格式。仅使用<img> 而不是<canvas>,这似乎是一个很大的开销。并且编码位图在内存方面似乎适得其反。
  • @Pandaiolo - 是的,同意数据网址;但是 blob url 具有类似的浏览器支持,您不必对数据进行 base64 编码。尽管您仍然必须编码为 PNG,然后浏览器必须再次解码,但您至少可以避免它的 base64 方面。

标签: javascript image image-processing bpg


【解决方案1】:

向图像添加错误事件处理程序。在 Chrome 40 上,当图像丢失或浏览器不知道如何显示时触发:

<script>
var errors = [];
function fallback(elt) {
    if(errors[elt.src]) return;
    // you should also extract the extension in order to test lena.bpg, lena.png, lena.jpg and not lena.bpg.png, lena.bpg.png.jpg
    errors[elt.src] = true;
    console.error('could not load image, falling back');
    elt.src = elt.src + '.png';
    // stop trying
    elt.onerror= function(){};
}
</script>
<img src="test.html" onerror="fallback(this);" width=300 height=300 />

优点:客户端部分没有内存/cpu 使用。 缺点:需要在服务器上提供备用图像。

我相信您可以在所有 img 标签上声明一个全局错误侦听器,因此这也适用于未来的图像。

【讨论】:

  • 嗯。但是 afaik 没有浏览器实际上原生支持 BPG。所以这实际上总是回退......(无论如何现在)这就是你的想法吗?
  • 我在想 BPG 可以在未来获得浏览器支持。这是乐观的。
【解决方案2】:

BPG 看起来确实很有希望。如果您想随时检测来自任何来源的&lt;img&gt; 元素的添加,您可以使用MutationObservers。 如果您不了解它们,它们是异步的,在文档中记录所有 DOM 突变的子集,并允许回调立即处理这些突变,而不是像 DOM 事件那样同步处理。因此,如果您在脚本中创建或更改大量图像的来源,观察者将等到您的脚本完成,然后一次性处理所有新图像(因此回调中的循环)。

以下假设您有一个名为 doSomethingToDecode(img) 的函数(对不起,我现在不打算提供帮助),它用(很可能)生成的 PNG 替换了 img 的 src。它可以异步执行此操作,这不是问题。此外,只要生成的替换不以“.bpg”结尾,您无需在交换其src 时停止观察图像。

当您在任何地方添加&lt;img&gt; 后代时,第一个观察者会做出反应(以及其他元素,但它会忽略这些);不幸的是,在一般情况下不可能对其进行太多优化。它必须遍历突变列表,然后是每个突变的新节点列表,因此是嵌套的for 循环。但是

imgObs=new MutationObserver(
    function(mutations){
        for(var i=0, m; m=mutations[i]; i++) if(m.addedNodes.length)
            for(var j=0, img; img=m.addedNodes[j]; j++) if(img.localName=="img"){
                if(img.src && /\.bpg$/.test(img.src))
                    doSomethingToDecode(img)
                srcObs.observe(img, srcOptions)
            }
    }
)

当您更改元素的 src 属性时,其他观察者会做出反应,并且应该只观察 &lt;img&gt; 元素(为了获得最佳性能,它没有故障保护,以防您让它观察其他元素,所以不要) .

srcObs=new MutationObserver(
    function(mutations){
        for(var i=0, m; m=mutations[i]; i++){
            var img=m.target
            if(img.src && /\.bpg$/.test(img.src))
                doSomethingToDecode(img)
        }
    }
)

还要把它放在手边,每次我们开始观察新图像时都需要它:

var srcOptions={childList:false, attributes:true, attributeFilter:["src"]}

您还可以创建一个观察者,对删除 &lt;img&gt; 元素做出反应,然后停止观察它们,并释放任何与解码相关的资源,但希望浏览器至少足够聪明,可以停止观察应该是垃圾的元素已收集(未经测试!)。

在加载 HTML 后运行此程序(不要等待包含图像和 CSS 等的整个页面)。注意:这是使用 DOM 级别 0 document.images 集合。非常老派,但它正在做我们想要的非常高效和简洁的事情,那为什么不呢?

所以首先你用 bpg 源解码现有的 &lt;img&gt;s,然后观察它们是否有 src 的变化:

for(var i=0, img; img=document.images[i]; i++){
    if(img.src && /\.bpg$/.test(img.src))
        doSomethingToDecode(img)
    srcObs.observe(img, srcOptions)
}

然后这告诉第一个观察者对整个文档的&lt;body&gt; 中的内容做出反应;不幸的是,没有tagNameFilter 参数可以本地过滤掉非&lt;img&gt; childList 突变。

imgObs.observe(document.body, {subtree:true, childList:true, attributes:false})

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2012-10-02
    • 2010-10-06
    • 2023-03-08
    • 1970-01-01
    • 2013-08-24
    • 2012-11-28
    • 1970-01-01
    相关资源
    最近更新 更多