静悄悄掀开 WebAssembly 的面纱 (四)- iOS 图片优化之 webp

WebAssembly 是通过 *.wasm 文件进行存储的,这是编译好的可移植、精悍、载入迅捷的二进制格式文件,它的体积非常的小。更多查看 webassembly 官网

.wasm 文件 与 .wat 文件的区别

.wat
.wasm

二、 WebAssembly 处于编译阶段哪个环节

WebAssembly 能做到像 Java 字节码一样,一次编译到处运行,具有跨平台特性。以此同时,作为中间码的 WebAssembly 直接省略编译前端的步骤,而 JavaScript 需要实时编译,相比之下性能优势显著

三、WebAssembly 怎么跟 js 互通

在浏览器中,提供了一个全局的 window.WebAssembly 对象,可以用于实例化 WASM 模块。

四、利用 WebAssembly 解决 WKwebview 宿主 iOS Safira 不支持解析 webp 的问题

先看 ios13.2.3 safari 解码 webp 图片与不使用 webp 编码加载时间对比 demo 中 webp_wasm.wasm 文件于 js 胶水 文件 webp_wasm.js 可通过 github 谷歌 libwebp 开源项目 readme的指引编译

二话不说直接上代码:

<!DOCTYPE html>
<html lang="en">

<head>
  <meta charset="UTF-8">
  <title>WASM demo of WebP decoding</title>
  <script type="text/javascript">
    var Module = {
      noInitialRun : true
    };
  </script>
  <script type="text/javascript">

function init() {
  var xhr = new XMLHttpRequest();
  xhr.open('GET', 'webp_wasm.wasm', true);
  xhr.responseType = 'arraybuffer';
  xhr.onload = function() {
    Module.wasmBinary = xhr.response;
    var script = document.createElement('script');
    script.src = "webp_wasm.js";
    document.body.appendChild(script);
  };
  xhr.send(null);
}

function decode(webp_data, canvas_id) {
  var result;
  if (Module["asm"] != undefined) {
    // wrapper for the function decoding a WebP into a canvas object
    WebpToCanvas = Module.cwrap('WebpToSDL', 'number', ['array', 'number']);
    // get the canvas to decode into
    // var canvas = document.getElementById(canvas_id);
    canvas = document.createElement('canvas');
    if (canvas == null) return;
    // clear previous picture (if any)
    Module.canvas = canvas;
    ctx = canvas.getContext('2d');
    ctx.clearRect(0, 0, canvas.width, canvas.height);
    // decode and measure timing
    start = new Date();
    var ret = WebpToCanvas(webp_data, webp_data.length); // webp 图像像素写入canvas
    console.log(ret);
    base64 = canvas.toDataURL("image/png");
    document.getElementById('decode_base64').src = base64;

    end = new Date();
    var decode_time = end - start;
    result = 'decoding time: ' + decode_time +' ms.';
  } else {
    result = "WASM module not finished loading! Please retry";
  }
  // display timing result
  speed_result = document.getElementById('timing');
  if (speed_result != null) {
    speed_result.innerHTML = '<p>'+ result + '</p>';
  }
}

function loadfile(filename, canvas_id) {
  var xhr = new XMLHttpRequest();
  xhr.open('GET', filename);
  xhr.responseType = 'arraybuffer';
  xhr.onreadystatechange = function() {
    if (xhr.readyState == 4 && xhr.status == 200) {
      var webp_data = new Uint8Array(xhr.response);
      decode(webp_data, canvas_id);
    }
  };
  xhr.send();
}


function loadImage(filename,img_id,time_id){
  var img = new Image();
  var start = new Date();
  var speed_result2 = document.getElementById(time_id);
  img.onload = function(){
  

    // display timing result
  if (speed_result2 != null) {
    document.getElementById('output_webp_img').appendChild(img);
    var end  = new Date();
    var decode_time = end - start;
    speed_result2.innerHTML = '<p>'+time_id+' decoding time: ' + decode_time +' ms.</p>';
    
  }   
  }
  img.src = filename;
 

}

  </script>
</head>

<body onload='init()' bgcolor='#f0f8ff'>
  <p>
    <strong>WebP demo using <a href="http://webassembly.org/">Web-Assembly</a></strong> -
  </p>
  <p>
    WASM version of the WebP decoder, using <a
    href="https://github.com/webmproject/libwebp">libwebp</a> compiled with
    <a href="https://github.com/kripken/emscripten/wiki">Emscripten</a>.
  </p>
  <p>
    <br/>
    Requires a <a href="https://developer.mozilla.org/en-US/docs/WebAssembly#Browser_compatibility">native-wasm
    enabled browser</a> (Chrome M58, WebKit)
    <br/>
  </p>

  <p id="image_buttons">
 
    <input type="button" value="lossy example" name="//img.alicdn.com/bao/uploaded/i4/2549599360/O1CN01YZ4MJz2J0vkikfMTT_!!0-item_pic.jpg_.webp"
           onclick="loadfile(this.name, 'output_canvas')">
    <input type="button" value="lossy+alpha example" name="./test2.webp"
           onclick="loadfile(this.name, 'output_canvas')">
    <input type="button" value="lossless example" name="./test3.webp"
           onclick="loadfile(this.name, 'output_canvas')">
  
           <input type="button" value="img load" onclick="loadImage(this.name,'output_webp_img','b_load_img')"  name="//img.alicdn.com/bao/uploaded/i4/2549599360/O1CN01YZ4MJz2J0vkikfMTT_!!0-item_pic.jpg">
           <input type="button" onclick="loadImage(this.name,'output_webp_img','b_load_webp_img')" value="img webp load" name="//img.alicdn.com/bao/uploaded/i4/2549599360/O1CN01YZ4MJz2J0vkikfMTT_!!0-item_pic.jpg_b.jpg_.webp">
 
  </p>
  <p id="timing">Timing: N/A</p>
  <p id="load_decode_time"></p>
  <p id="b_load_webp_img"></p>
  <p id="b_load_img"></p>
  <div id="output_webp_img"></div>
  <canvas id="output_canvas">Your browser does not support canvas</canvas>
  <img id="decode_base64">

</body>
</html>

复制代码

参考文章

我来评几句
登录后评论

已发表评论数()

相关站点

+订阅
热门文章