libjxl

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

client_worker.js (2753B)


      1 // Copyright (c) the JPEG XL Project Authors. All rights reserved.
      2 //
      3 // Use of this source code is governed by a BSD-style
      4 // license that can be found in the LICENSE file.
      5 
      6 let decoder = null;
      7 
      8 // Serialize work; plus postpone processing until decoder is ready.
      9 let jobs = [];
     10 
     11 const processJobs = () => {
     12   // Decoder not yet loaded.
     13   if (!decoder) {
     14     return;
     15   }
     16 
     17   while (true) {
     18     let job = null;
     19     // Currently we do not do progressive; process only "inputComplete" jobs.
     20     for (let i = 0; i < jobs.length; ++i) {
     21       if (!jobs[i].inputComplete) {
     22         continue;
     23       }
     24       job = jobs[i];
     25       jobs[i] = jobs[jobs.length - 1];
     26       jobs.pop();
     27       break;
     28     }
     29     if (!job) {
     30       return;
     31     }
     32     console.log('CW job: ' + job.uid);
     33     const input = job.input;
     34     let totalInputLength = 0;
     35     for (let i = 0; i < input.length; i++) {
     36       totalInputLength += input[i].length;
     37     }
     38 
     39     // TODO(eustas): persist to reduce fragmentation?
     40     const buffer = decoder._malloc(totalInputLength);
     41     // TODO(eustas): check OOM
     42     let offset = 0;
     43     for (let i = 0; i < input.length; ++i) {
     44       decoder.HEAP8.set(input[i], buffer + offset);
     45       offset += input[i].length;
     46     }
     47     let t0 = Date.now();
     48     // TODO(eustas): check result
     49     const result = decoder._jxlDecompress(buffer, totalInputLength);
     50     let t1 = Date.now();
     51     const msg = 'Decoded ' + job.url + ' in ' + (t1 - t0) + 'ms';
     52     // console.log(msg);
     53     decoder._free(buffer);
     54     const outputLength = decoder.HEAP32[result >> 2];
     55     const outputAddr = decoder.HEAP32[(result + 4) >> 2];
     56     const output = new Uint8Array(outputLength);
     57     const outputSrc = new Uint8Array(decoder.HEAP8.buffer);
     58     output.set(outputSrc.slice(outputAddr, outputAddr + outputLength));
     59     decoder._jxlCleanup(result);
     60     const response = {uid: job.uid, data: output, msg: msg};
     61     postMessage(response, [output.buffer]);
     62   }
     63 };
     64 
     65 onmessage = function(event) {
     66   const data = event.data;
     67   console.log('CW received: ' + data.op);
     68   if (data.op === 'decodeJxl') {
     69     let job = null;
     70     for (let i = 0; i < jobs.length; ++i) {
     71       if (jobs[i].uid === data.uid) {
     72         job = jobs[i];
     73         break;
     74       }
     75     }
     76     if (!job) {
     77       job = {uid: data.uid, input: [], inputComplete: false, url: data.url};
     78       jobs.push(job);
     79     }
     80     if (data.data) {
     81       job.input.push(data.data);
     82     } else {
     83       job.inputComplete = true;
     84     }
     85     processJobs();
     86   }
     87 };
     88 
     89 const onLoadJxlModule = (instance) => {
     90   decoder = instance;
     91   processJobs();
     92 };
     93 
     94 importScripts('jxl_decoder.js');
     95 const config = {
     96   mainScriptUrlOrBlob: 'https://jxl-demo.netlify.app/jxl_decoder.js',
     97   INITIAL_MEMORY: 16 * 1024 * 1024,
     98 };
     99 JxlDecoderModule(config).then(onLoadJxlModule);