// SPDX-License-Identifier: LGPL-3.0-or-later // Pinned libheif build supplied by heic-to. A dedicated worker permits immediate // cancellation and releases decoder memory; no nested hidden worker is retained. import buildLibheif from '../node_modules/heic-to/src/lib/libheif-without-unsafe-eval.js'; import {orientRgba} from './heic-orientation.js'; import {heicPreflight} from './heic-preflight.js'; self.onmessage=async({data})=>{ let lib,decoder,images,canvas; try{ const bytes=new Uint8Array(data),metadata=heicPreflight(bytes);lib=buildLibheif();decoder=new lib.HeifDecoder();images=decoder.decode(bytes); if(images.length!==1)throw Error('Multiple-image HEIC files are not supported. Export one still image first.'); const image=images[0],w=image.get_width(),h=image.get_height();if(!w||!h||w*h>16000000)throw Error('Keep each HEIC under 20 MB and 16 megapixels.'); const pixels=new ImageData(w,h);await new Promise((resolve,reject)=>image.display(pixels,result=>result?resolve():reject(Error('Unable to decode this HEIC. Convert it to JPG first.')))); const oriented=orientRgba(pixels.data,w,h,metadata.orientation); canvas=new OffscreenCanvas(oriented.width,oriented.height);const context=canvas.getContext('2d',{colorSpace:'srgb'}); // ImageData carries the source primaries; Canvas converts Display-P3 to sRGB // for predictable PNG/PDF output instead of relabelling the decoded pixels. const tagged=new ImageData(oriented.data,oriented.width,oriented.height,{colorSpace:metadata.colorSpace}); if(metadata.colorSpace!=='srgb'&&tagged.colorSpace!==metadata.colorSpace)throw Error('This browser cannot preserve the HEIC colour profile. Convert it to JPG first.'); context.putImageData(tagged,0,0);const blob=await canvas.convertToBlob({type:'image/png'}); if(blob.size>50*1024*1024)throw Error('The decoded image is too large. Use a smaller image.'); const output=await blob.arrayBuffer();self.postMessage({bytes:output,width:oriented.width,height:oriented.height},[output]); }catch(e){self.postMessage({error:e.message||'Unable to decode this HEIC. Convert it to JPG first.'});} finally{for(const image of images||[])image.free();if(decoder?.decoder)lib.heif_context_free(decoder.decoder);if(canvas)canvas.width=canvas.height=0;self.close();} };