Skip to main content

ReShade With HDR JPEG XL Support

So I have been fiddling around with ReShade for quite some time, trying to give it a capability to capture screenshot in JPEG XL format. However I was kind of stuck in Visual Studio's dependency hell when trying to integrate libjxl to ReShade build system rather than tinkering with the implementation. Well, to be fair, Visual Studio is not my IDE of choice and I have little experience with it, so...

Fast forward 10 months later, I just realized that ReShade already have HDR support and already incorporating HDR PNG as a screenshot format. This tickles my mind to continue experimenting with JPEG XL support again. Furthermore, I just found out that libjxl team also releasing simple-lossless-encoder demo that can fit on a single cc file, this is perfect as this can keep ReShade binary size low and shouldn't complicate the deps, plus I also focused on lossless side for a fast encode (effort 1).

Linear Color Analysis of Modern Image Formats

It has been a standard for a long time that web image should have delivered in sRGB color profile. This was chosen mainly for compatibility reasons, because most of the browsers back then didn't have a proper color management, therefore color profiles were ignored and can be incorrectly rendered -- as without a color profile (aka. untagged) any image will be considered as sRGB. This was not a concern since most of the consumer displays at that time are barely even have full coverage of sRGB gamut.

I remebered during my college days when I still have a side job to calibrate monitors (that was way back in 2012-ish, when Spyder 4 was released), most of my customers' screen only have around 70% sRGB coverage, I even found some that went as low as 60%! Ouch! Wide gamut, or even a full sRGB coverage monitors were pipedream to most of us, we can only see them in big studios and production houses.

Anyway, I digress with my personal story.

And thus, since the advent of wide gamut displays and HDR these days, color management in browsers became an important aspect. We are no longer bounded by sRGB profile, many new wide-gamut profiles are emerged that can accomodate this shiny new display (pun intended), such as DisplayP3 and Rec.2020 profiles. Therefore, now major browsers have a proper color management to properly view those images, also to pave the road for HDR viewing support.

Well, actually in photography section we already got used to work with wide-gamut profiles such as Adobe RGB and ProPhoto RGB for a pretty long time too.

PSO2NGS Pink CAST Dragon Showcase

My current favorite T2 kemono CAST look on NGS~ The combination of white, black, and pink color scheme, along with a subtle touch of fabric in a CAST body!

Supposed to be a wingless dragon, but the mask made it more like a dragon-fox hybrid.

Parts Used

Here's the main parts list:

  • Body: Gerifalte Body
    • one of the few fully-armored T2 body 💗
  • Arms: Krolik Arms/B
  • Legs: N-Amuaira Legs V2
  • Head: Moonlight Hair/D

Accessories:

  • Head: Sylphos Mask, Rithia Hair Ornament, Cat Eye Contacts
  • Others: MC96 Field Walker, Mechanical Fin/B, Dinorex Tail

Let's start the showcase then! :3

PSO2NGS Blue CAST Dragon Showcase

A journey to find a perfect furry/kemono (robot) in NGS continues! This time I got the idea when Lion Head Shield acc is out, turns out I can place it on the head!

Ugh, if only we have big claw arms to complete it...

Parts Used

Here's the main parts list:

  • Body: Ruka Body
  • Arms: Ruka Arms/B (should have used the normal version to match the grunge...)
  • Legs: Dinorex Legs
  • Head: Pro Vosse Head

Accessories:

  • Head: Lion Head Shield, Krolik Headgear/B
  • Others: Big Robot Shoes/B, Tri Fin Blade, Dinorex Tail

Let's start the showcase then! :3

Krita 5.2 JPEG XL Export Tips

Intro

With the release of version 5.2, Krita brings a lot of JPEG XL improvement! However with added knobs and switches here and there, it can be pretty confusing for a standard user... x3

Here I'll try to give some tips to use it efficiently!

JPEG XL?

JPEG XL (or JXL for short) is a relatively new image standard by the JPEG committee (yes, the old JPEG that we all familiar with!). It's aimed to be a long-term replacement for web image delivery formats like the old JPEG and PNG. It also have basic animation function like GIF and APNG, and can have a basic layering function as well! Better compression ratio, HDR support, animation support, and up to 32-bit depth support is just a few of their enticing features for me! I myself beginning to phase out PNG for my workflow in digital painting in favor of JXL, especially for lossless storage.. Moreover on HDR pics, no more TIFF for storing simple images!

PSO2NGS Blue CAST Fox Showcase

A showcase of one of my favorite phasion set on PSO2NGS ^^ Smol blue CAST/robot-ish fox.

Most of the parts are from the base game, but I think it still looks good even on NGS! Totally love the legs part!

Parts Used

Here's the main parts list:

  • Body: Sylphos Body
  • Arms: Sapphir Arms CV
  • Legs: Grizz Legs CV
  • Head: Di Gant Head/B (but this is just a placeholder)

Accessories:

  • Head: Sylphos mask, Aile Headgear, Krolik Headgear/B, Rithia Hair Ornament
  • Others: Crimpiaco Cape, Fluffy Gloves: White

Let's start the showcase then! :3

Hidden Art of Unclamping jxlart Artworks

Background Story

On my post about JPEG XL color analysis I mentioned that JXL stores lossy XYB in absolute, float values that can be requested during decoding process by calling pixel format data_type as JXL_TYPE_FLOAT, where out-of-gamut colors are represented with negative values.

I was recently encouraged by Amyspark from Krita to write my python Color Gamut Plotter to something native, like Qt or web-based. As I also doing hacks and sometimes contributing to Krita as well, I took the Qt path as a base. Furthermore, I'm still more comfortable coding with C/C++ rather than JS, might as well training more with Qt~ :3

Fiddling With Docusaurus

depends on how you view it, but I don't feel like reinventing a wheel just to make a static blog site. haha
On the positive side, I can throw JPEG-XL images here too and get it rendered on supported browsers, yay!

![Spectral Zephyr](./zeph-spectral.jxl)

Spectral Zephyr

zooming

May break on JXL-unsupported browsers if you try to zoom a broken/unrendered image and may freeze the page! For example I use react-medium-image-zoom plugin for image zooming in this page.

Although Docusaurus always complains a lot during compile time:

[WARNING] The image at "{path_to_image.jxl}" can't be read correctly. Please ensure it's a valid image.
unsupported file type: undefined (file: {path_to_image.jxl})

And nope, using JSX didn't work either...

ERROR in {path_to_image.jxl} 1:0
Module parse failed: Unexpected character '' (1:0)
You may need an appropriate loader to handle this file type, currently no loaders are configured to process this file. See https://webpack.js.org/concepts#loaders
(Source code omitted for this binary file)

So yeah, sadly <picture> tag didn't work with JXL here either!


EDIT: Found some workaround yay!

  • The first one is to insert file-loader! before the URL, for example image below:

    <picture>
    <source srcSet={require("file-loader!./dv-nebia-nevia-sub.jxl").default} type="image/jxl"/>
    <img src={require("./dv-nebia-nevia-sub.jpg").default} width="100%" />
    </picture>

    However, this method requires a manual insertion for each <picture> tag and will strip any filenames (which is sad!). If the image is still broken, use !!file-loader! instead. Or maybe Docusaurus already fixed the module on the next method!

  • The second method requires to fiddle with Docusaurus' webpackUtils source which will use the internal parsing and keeping the filename intact:

    On node_modules, find webpackUtils.js and/or webpackUtils.ts. In my case it's on node_modules/@docusaurus/utils/lib/. Open the file and find getFileLoaderUtils() function, on const rules variable find image field and add jxl to the list:

    images: () => ({
    use: [loaders.url({ folder: 'images' })],
    test: /\.(?:ico|jpe?g|png|gif|webp|avif|jxl)(?:\?.*)?$/i,
    }),

    This way we don't need to add file-loader! and just add an URL like usual!

    <picture>
    <source srcSet={require("./dv-nebia-nevia-sub.jxl").default} type="image/jxl"/>
    <img src={require("./dv-nebia-nevia-sub.jpg").default} width="100%" />
    </picture>

Example result:

And there you have it! JPEG XL-enabled Docusaurus with fallback image!

Spare me, I'm still a total noob in node.js development... I'm not even sure if those methods are safe, please ping me if you found something!