libjxl

FORK: libjxl patches used on blog
git clone https://git.neptards.moe/blog/libjxl.git
Log | Files | Refs | Submodules | README | LICENSE

README.md (5721B)


      1 ## WebAssembly demonstration
      2 
      3 This folder contains an example how to decode JPEG XL files on a web page using
      4 WASM engine.
      5 
      6 ### One line demo
      7 
      8 The simplest way to get support of JXL images on the client side is simply to
      9 link one extra script (`<script src="service_worker.js">`) to the page.
     10 This script installs a `ServiceWorker` that:
     11 
     12  - checks if the browser supports the JXL image format already
     13  - if it is not, then advertise `image/jxl` as media format in image requests
     14  - then, if the server responds with `image/jxl` content it gets decoded and
     15    re-encoded to PNG on the fly
     16 
     17 Generally the message / data flow looks the following way:
     18 
     19  - `Fetch API` receives a resource request from client page (e.g. when the HTML
     20    engine discovers an `img` tag) and asks the `ServiceWorker` how to proceed
     21  - the `ServiceWorker` alters the request and uses the `Fetch API`
     22    to obtain data
     23  - when data arrives, the `ServiceWorker` forwards it to the "client"
     24    (the page) that initiated the resource request
     25  - the client forwards the data to a worker (see `client_worker.js`) to avoid
     26    processing in the "main loop" thread
     27  - a worker does the actual decoding; to make it faster several additional
     28    workers are spawned (to enable multi-threading in WASM module);
     29    the decoded image is wrapped in non-compressed PNG format and sent back
     30    to client
     31  - the client relays image data to `ServiceWorker`
     32  - the `ServiceWorker` passes data to `Fetch API` as a response to initial
     33    resource request
     34 
     35 Despite the additional "hop" (client) in the flow, data is not copied every
     36 time but rather "transferred" between the participants.
     37 
     38 Demo page: `one_line_demo.html`. Extended demo, that also shows how long it
     39 took do decode images: `one_line_demo_with_console.html`.
     40 
     41 Page that shows "manual" decoding (and has benchmarking capabilities):
     42 `manual_decode_demo.html`.
     43 
     44 ### Hosting
     45 
     46 To enable multi-threading some files should be served in a secure context (i.e.
     47 transferred over HTTPS) and executed in a "site-isolation" mode (controlled by
     48 COOP and COEP response headers).
     49 
     50 Unfortunately [GitHub Pages](https://pages.github.com/) does not allow setting
     51 response headers.
     52 
     53 [Netlify](https://www.netlify.com/) provides free, easy to setup and deploy
     54 platform for serving such demonstration sites. However, any other
     55 service provider / software that allows changing response headers could be
     56 employed as well.
     57 
     58 `netlify.toml` and `netlify/precompressed.ts` specify the serving rules.
     59 Namely, some requests get "upgraded" responses:
     60 
     61  - if a request specifies that `brotli` compression is supported,
     62    then precompressed entries are sent
     63  - if a request specifies that `image/jxl` format is allowed,
     64    then entries transcoded to JXL format are sent
     65 
     66 ### How to build the demo
     67 
     68 `build_site.py` script takes care of JavaScript minification, template
     69 substitution and resource compression. Its arguments are:
     70 
     71  - source path: site template directory (that contains this README file)
     72  - binary path: build directory, that contains compiled WASM module
     73  - output path
     74 
     75 To complete the site few more files are to be added to output directory:
     76 
     77  - `image00.jpg`, `image01.png` demo images; will be shown if `ServiceWorker`
     78    is not yet operable (fallback); to see those one could initiate
     79    "hard page reload" (press Shift-(Ctrl|Cmd)-R)
     80  - `image00.jpg.jxl`, `image01.png.jxl` demo images in JXL format
     81  - `imageNN.jxl` images for "manual" decoding demo; NN is a number starting
     82    form `00`
     83  - `favicon.ico` is an optional site icon
     84  - `index.html` is an optional site "home" page
     85 
     86 In the source code (`service_worker.js`) there are two compile-time constants
     87 that modify the behaviour of Service Worker:
     88 
     89  - `FORCE_COP` flag allows rewriting responses to add COOP / COEP headers;
     90    this is useful when it is difficult / impossible to setup response headers
     91    otherwise (e.g. GitHub Pages)
     92  - `FORCE_DECODING` flag activate JXL decoding when image response type has
     93    `Content-Encoding` header set to `application/octet-stream`; this happens
     94    when server does not know the JXL MIME-type
     95 
     96 One dependency that `build_site.py` requires is [uglifyjs](https://github.com/mishoo/UglifyJS), which can be installed with
     97 ```
     98 npm install uglify-js -g
     99 ```
    100 If you followed the [wasm build instructions](../../docs/building_wasm.md),
    101 assuming you are in the root level of the cloned libjxl repo a typical call to
    102 build the site would be
    103 ```bash
    104 python3 ./tools/wasm_demo/build_site.py ./tools/wasm_demo/ ./build-wasm32/tools/wasm_demo/ /path/to/demo-site
    105 ```
    106 Then you need to put your image files in the correct same place and are should be good to go.
    107 
    108 
    109 To summarize, using the wasm decoder together with a service workder amounts to adding
    110 ```html
    111 <script src="service_worker.js"></script>
    112 ```
    113 to your html and then putting the `service_worker.js` and `jxl_decoder.wasm` binary in directory where they can be read.
    114 
    115 
    116 It is not guaranteed, but somewhat fresh demo is hosted on
    117 `https://jxl-demo.netlify.app/`, e.g.:
    118 
    119  - [one line demo](https://jxl-demo.netlify.app/one_line_demo_with_console.html)
    120  - [one line demo with console](https://jxl-demo.netlify.app/one_line_demo.html)
    121  - [manual decode demo](https://jxl-demo.netlify.app/manual_decode_demo.html?img=1&colorSpace=rec2100-pq&runBenchmark=30&wantSdr=false&displayNits=1500);
    122    URL contains query parameters that control rendering and benchmarking options;
    123    please note, that HDR canvas is often not enabled by default, it could be
    124    enabled in some browsers via `about://flags/#enable-experimental-web-platform-features`
    125  - [`service_worker.js`](https://jxl-demo.netlify.app/service_worker.js)
    126  - [`jxl_decoder.wasm`](https://jxl-demo.netlify.app/jxl_decoder.wasm)