DEV Community

Cover image for Adding JPEG XL & QOI Support to my Website OS
Dustin Brett
Dustin Brett

Posted on

Adding JPEG XL & QOI Support to my Website OS

I'm always having fun adding things to my desktop environment in the browser (daedalOS), which also powers my personal website dustinbrett.com where everything I show here can be tried out.

Recently I'd added TIFF support to my project via UTIF.js and now I decided I wanted to add JPEG XL & QOI.

JPEG XL Support (Sample Images)

JPEG XL Images

For adding JPEG XL support I went with jxl.js which I modified for my use case. After looking through the main file, which is also called jxl.js, I decided I only needed 2 relevant code blocks. The one to decode the image and the one to turn the ImageData into something I could display in my existing codebase (which I already partially had implemented for another use case).

To decode the image it creates a worker with jxl_dec.js, also I updated the path (hardcoded inside jxl_dec.js) for jxl_dec.wasm to point to where I've stored it within my Next.js public directory.

Then all that is needed is to run decodeJxl with image data in Buffer/Uint8Array form. Once it returns ImageData I use imgDataToBuffer to convert it back into a Buffer which I use for making thumbnails and displaying the picture in the Photos app.

type JxlDecodeResponse = { data: { imgData: ImageData } };

export const decodeJxl = async (image: Buffer): Promise<ImageData> =>
  new Promise((resolve) => {
    const worker = new Worker("System/JXL.js/jxl_dec.js");

    worker.postMessage({ image, jxlSrc: "image.jxl" });
    worker.addEventListener("message", (message: JxlDecodeResponse) =>
      resolve(message?.data?.imgData)
    );
  });

export const imgDataToBuffer = (imageData: ImageData): Buffer => {
  const canvas = document.createElement("canvas");

  canvas.width = imageData.width;
  canvas.height = imageData.height;
  canvas.getContext("2d")?.putImageData(imageData, 0, 0);

  return Buffer.from(
    canvas?.toDataURL("image/png").replace("data:image/png;base64,", ""),
    "base64"
  );
};
Enter fullscreen mode Exit fullscreen mode

QOI Support (Sample Images)

QOI Images

When it came to adding QOI support, I used an open source "Gist" example that I basically didn't touch except to turn the qoi.js file into a .ts file so I could export a function which wrapped transcode_qoi_to_png and exported it as a Buffer for my use cases.

export const decodeQoi = (imgBuffer: Buffer): Buffer =>
  Buffer.from(new Uint8Array(transcode_qoi_to_png(new Uint8Array(imgBuffer))));
Enter fullscreen mode Exit fullscreen mode

Thanks! (@DustinBrett)

I hope you enjoyed my article about adding image formats to my desktop environment in the browser. If you're interested in more stuff about my side project which I have been working on for over 2 years, I recently did a video going over 2022's progress.

Please check it out and leave a comment/like if you enjoy it or have something to say.

Top comments (2)

Collapse
 
gilfewster profile image
Gil Fewster

Great project. Looks like a lot of fun to work on.

Collapse
 
dustinbrett profile image
Dustin Brett

Thanks very much! Ya it was important to me that the project I worked on would allow me to jump around to different things to keep learning and not get bored. This month has been adding image format support I guess.