<?xml version="1.0" encoding="utf-8"?>
<feed xmlns="http://www.w3.org/2005/Atom">
    <id>https://saklistudio.com/miniblog/</id>
    <title>Kampidh's Blog Blog</title>
    <updated>2025-06-20T10:57:00.000Z</updated>
    <generator>https://github.com/jpmonette/feed</generator>
    <link rel="alternate" href="https://saklistudio.com/miniblog/"/>
    <subtitle>Kampidh's Blog Blog</subtitle>
    <icon>https://saklistudio.com/miniblog/img/favicon-w.png</icon>
    <entry>
        <title type="html"><![CDATA[ReShade With HDR JPEG XL Support]]></title>
        <id>https://saklistudio.com/miniblog/reshade-jpegxl-saga</id>
        <link href="https://saklistudio.com/miniblog/reshade-jpegxl-saga"/>
        <updated>2025-06-20T10:57:00.000Z</updated>
        <summary type="html"><![CDATA[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...]]></summary>
        <content type="html"><![CDATA[<p>So I have been fiddling around with <a href="https://github.com/crosire/reshade" target="_blank" rel="noopener noreferrer">ReShade</a> 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 <a href="https://github.com/libjxl/libjxl" target="_blank" rel="noopener noreferrer">libjxl</a> to ReShade build system rather than tinkering with the implementation. <em>Well, to be fair, Visual Studio is not my IDE of choice and I have little experience with it, so...</em></p>
<p>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 <a href="https://github.com/libjxl/simple-lossless-encoder" target="_blank" rel="noopener noreferrer">simple-lossless-encoder</a> 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).</p>
<!-- -->
<p>After <del>stealing</del> adapting the demo code, adding few paths to allow few other color profiles (2020 PQ and linear sRGB) and float bitdepth, it finally lives! HDR screenshot with JPEG XL!</p>
<h2 class="anchor anchorWithStickyNavbar_LWe7" id="hdr-comparison">HDR Comparison<a class="hash-link" aria-label="Direct link to HDR Comparison" title="Direct link to HDR Comparison" href="https://saklistudio.com/miniblog/reshade-jpegxl-saga#hdr-comparison">​</a></h2>
<p><em>For a proper HDR viewing, you should view these with HDR (and JXL) enabled browser and HDR monitor</em></p>
<div aria-owns="rmiz-modal-" data-rmiz=""><div data-rmiz-content="not-found" style="visibility:visible"><img src="https://saklistudio.com/miniblog/blog-img/reshadejxlsaga/pso2-hdr.jxl" alt="PSO2NGS HDR JPEG XL" style="max-width:100%;height:auto"></div></div>
<center>JPEG XL - 5.49MB</center>
<p>And here's the PNG one for the comparison:</p>
<div aria-owns="rmiz-modal-" data-rmiz=""><div data-rmiz-content="not-found" style="visibility:visible"><img src="https://saklistudio.com/miniblog/blog-img/reshadejxlsaga/pso2-hdr.png" alt="PSO2NGS HDR PNG" style="max-width:100%;height:auto"></div></div>
<center>PNG - 8.78MB</center>
<p>Not only that it's smaller than PNG, it also encodes much faster:</p>
<div aria-owns="rmiz-modal-" data-rmiz=""><div data-rmiz-content="not-found" style="visibility:visible"><img src="https://saklistudio.com/miniblog/blog-img/reshadejxlsaga/hdr-speed-bench.png" alt="HDR Speed comparison" style="max-width:100%;height:auto"></div></div>
<p>It seems like in HDR PNG they do some color conversion that contributes to that heavy processing, while in JXL I only did buffer conversion (<code>R10G10B10A2</code> to <code>R16G16B16</code>) without scaling, preserving 10 bit values <code>0-1023</code>.</p>
<h2 class="anchor anchorWithStickyNavbar_LWe7" id="sdr-comparison">SDR Comparison<a class="hash-link" aria-label="Direct link to SDR Comparison" title="Direct link to SDR Comparison" href="https://saklistudio.com/miniblog/reshade-jpegxl-saga#sdr-comparison">​</a></h2>
<div aria-owns="rmiz-modal-" data-rmiz=""><div data-rmiz-content="not-found" style="visibility:visible"><img src="https://saklistudio.com/miniblog/blog-img/reshadejxlsaga/pso2-sdr.jxl" alt="PSO2NGS SDR JPEG XL" style="max-width:100%;height:auto"></div></div>
<center>JPEG XL - 4.41MB</center>
<p>And here's the PNG one for the comparison:</p>
<div aria-owns="rmiz-modal-" data-rmiz=""><div data-rmiz-content="not-found" style="visibility:visible"><img src="https://saklistudio.com/miniblog/blog-img/reshadejxlsaga/pso2-sdr.png" alt="PSO2NGS SDR PNG" style="max-width:100%;height:auto"></div></div>
<center>PNG - 5.38MB</center>
<p>They're pretty similar in speed!</p>
<div aria-owns="rmiz-modal-" data-rmiz=""><div data-rmiz-content="not-found" style="visibility:visible"><img src="https://saklistudio.com/miniblog/blog-img/reshadejxlsaga/sdr-speed-bench.png" alt="SDR Speed comparison" style="max-width:100%;height:auto"></div></div>
<hr>
<p>As for the source code, it's still a draft with a bunch of debug prints enabled, but feel free to check here: <a href="https://github.com/kampidh/reshade/tree/jpegxl-simple" target="_blank" rel="noopener noreferrer">https://github.com/kampidh/reshade/tree/jpegxl-simple</a></p>
<p>I also have prebuilt binaries in case of someone want to test it: <a href="https://kampidh.com/secshare/static?f=803cac3f5d1002476456cc81e87935148f6ac934fa0f1583485b9a83081a74bb" target="_blank" rel="noopener noreferrer">self hosted link</a></p>
<p><em>PS: Do take a lot of precaution when downloading binaries please, as this is NOT an official build and might have bunch of nasty bugs. You also probably should only test it on a single-player game. Use at your own risk, thank you~</em></p>]]></content>
        <author>
            <name>Zephyra</name>
            <uri>https://saklistudio.com</uri>
        </author>
        <category label="JPEG XL" term="JPEG XL"/>
        <category label="ReShade" term="ReShade"/>
        <category label="gaming" term="gaming"/>
        <category label="modding" term="modding"/>
        <category label="shaders" term="shaders"/>
    </entry>
    <entry>
        <title type="html"><![CDATA[Linear Color Analysis of Modern Image Formats]]></title>
        <id>https://saklistudio.com/miniblog/modern-image-format-linear-color-analysis</id>
        <link href="https://saklistudio.com/miniblog/modern-image-format-linear-color-analysis"/>
        <updated>2024-08-20T20:10:00.000Z</updated>
        <summary type="html"><![CDATA[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.]]></summary>
        <content type="html"><![CDATA[<p>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.</p>
<p>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.</p>
<p>Anyway, I digress with my personal story.</p>
<p>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.</p>
<p><em>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.</em></p>
<!-- -->
<hr>
<h2 class="anchor anchorWithStickyNavbar_LWe7" id="an-unideal-scenario---lossy-compression">An Unideal Scenario - Lossy Compression<a class="hash-link" aria-label="Direct link to An Unideal Scenario - Lossy Compression" title="Direct link to An Unideal Scenario - Lossy Compression" href="https://saklistudio.com/miniblog/modern-image-format-linear-color-analysis#an-unideal-scenario---lossy-compression">​</a></h2>
<p>Now imagine this scenario, you're just a photographer working with these profiles (say for my example here, darktable's Linear ProPhoto RGB), and you just forget to convert the pictures into a web-friendly profile when deploying them. How well do these modern image codecs handle this? In my experience, wide-gamut linear profiles often hits hard for a lossy image compression... Let's investigate!</p>
<p>For the test image, I will be using this picture of color patches from an old XRite ColorChecker Passport. This was shot with Nikon D810 + 105mm f/2.8G VR Micro-Nikkor lens @ f/8.0 ISO 64 under Broncolor Siros lights.</p>
<p><a href="https://saklistudio.com/miniblog/assets/files/raw-photo-2156aa043715847b8782d3db748eccc9.png" target="_blank">Lossless 16bpc(48bpp) PNG with Linear ProPhoto RGB - 20.6 MiB</a></p>
<p>Conversion tools (all with metadata intact, minor impact though):</p>
<ul>
<li>JPEG XL: <code>cjxl 0.10.3</code></li>
<li>AVIF: <code>avifenc 1.1.1</code></li>
<li>WebP: <code>Krita 5.2.3 WebP export</code></li>
</ul>
<p>All encoding done with default parameters, only changing the <code>quality</code> parameter.</p>
<p>For the plotting tool I'll be using is my own <a href="https://github.com/kampidh/Color-Gamut-Plotter-QtVer" target="_blank" rel="noopener noreferrer">Color Gamut Plotter written in Qt</a>, however I'm not suggesting that you should try it since it's still buggy and unwieldy at best xD, but feel free to try it if you insist. <em><a href="https://www.youtube.com/watch?v=-Nco5DqGsRQ" target="_blank" rel="noopener noreferrer">I also have a showcase video on YouTube</a></em>. Currently it has support to only read jpg, png, tiff, and jxl as an input. Originally Qt also have webp but I disabled it since I haven't been able to upgrade it to mitigate that one big <code>CVE-2023-4863</code>. Therefore you'll see why AVIF and WebP test files used for plotting is a decoded image (to 16bpc PNG). As for the colorspace display, I will be using <a href="https://bottosson.github.io/posts/oklab/" target="_blank" rel="noopener noreferrer">peceptual space, Oklab</a>. For JPEG XL, this tool decodes with libjxl <code>0.10.2</code> and pulling the pixel data as 32-bit float, therefore you might see the results below that it sometimes gives more total unique colors than the RAW PNG.</p>
<div style="display:flex;flex-flow:wrap;max-width:100%;margin:16px 0;justify-content:center"><figure style="max-width:49%;margin:8px 0.25%"><div style="max-width:100%"><div aria-owns="rmiz-modal-" data-rmiz=""><div data-rmiz-content="not-found" style="visibility:visible"><picture><source srcset="/miniblog/blog-img/jxlvother/plots-jxl//raw.jxl" type="image/jxl"><img src="https://saklistudio.com/miniblog/blog-img/jxlvother/plots-jxl//raw.png" alt=""></picture></div></div></div><figcaption style="text-align:center;font-style:italic">RAW - Color plot<br>With Post-2014 ColorChecker targets</figcaption></figure><figure style="max-width:49%;margin:8px 0.25%"><div style="max-width:100%"><div aria-owns="rmiz-modal-" data-rmiz=""><div data-rmiz-content="not-found" style="visibility:visible"><picture><source srcset="/miniblog/blog-img/jxlvother/plots-jxl//raw-distrib.jxl" type="image/jxl"><img src="https://saklistudio.com/miniblog/blog-img/jxlvother/plots-jxl//raw-distrib.png" alt=""></picture></div></div></div><figcaption style="text-align:center;font-style:italic">RAW - Distribution / occurrence plot<br>Brighter = more pixels in that specific color</figcaption></figure></div>
<div class="theme-admonition theme-admonition-note admonition_xJq3 alert alert--secondary"><div class="admonitionHeading_Gvgb"><span class="admonitionIcon_Rf37"><svg viewBox="0 0 14 16"><path fill-rule="evenodd" d="M6.3 5.69a.942.942 0 0 1-.28-.7c0-.28.09-.52.28-.7.19-.18.42-.28.7-.28.28 0 .52.09.7.28.18.19.28.42.28.7 0 .28-.09.52-.28.7a1 1 0 0 1-.7.3c-.28 0-.52-.11-.7-.3zM8 7.99c-.02-.25-.11-.48-.31-.69-.2-.19-.42-.3-.69-.31H6c-.27.02-.48.13-.69.31-.2.2-.3.44-.31.69h1v3c.02.27.11.5.31.69.2.2.42.31.69.31h1c.27 0 .48-.11.69-.31.2-.19.3-.42.31-.69H8V7.98v.01zM7 2.3c-3.14 0-5.7 2.54-5.7 5.68 0 3.14 2.56 5.7 5.7 5.7s5.7-2.55 5.7-5.7c0-3.15-2.56-5.69-5.7-5.69v.01zM7 .98c3.86 0 7 3.14 7 7s-3.14 7-7 7-7-3.12-7-7 3.14-7 7-7z"></path></svg></span>note</div><div class="admonitionContent_BuS1"><p>Correct me, I'm not quite sure if "Distribution / occurrence plot" is the correct term for the second plot. I don't know what's the proper scientific term for it.</p></div></div>
<p>Not a perfect calibration, but some was close enough to the colorchecker targets, darktable reported at <code>Max ~4.06dE</code> and <code>Avg ~1.92dE</code> using their <code>color calibration</code> module. We can see how the colors are clumped pretty nicely on the distribution plot.</p>
<hr>
<h2 class="anchor anchorWithStickyNavbar_LWe7" id="comparison-at-1bpp">Comparison At ~1bpp<a class="hash-link" aria-label="Direct link to Comparison At ~1bpp" title="Direct link to Comparison At ~1bpp" href="https://saklistudio.com/miniblog/modern-image-format-linear-color-analysis#comparison-at-1bpp">​</a></h2>
<h3 class="anchor anchorWithStickyNavbar_LWe7" id="color-plot">Color Plot<a class="hash-link" aria-label="Direct link to Color Plot" title="Direct link to Color Plot" href="https://saklistudio.com/miniblog/modern-image-format-linear-color-analysis#color-plot">​</a></h3>
<div style="display:flex;flex-flow:wrap;max-width:100%;margin:16px 0;justify-content:center"><figure style="max-width:49%;margin:8px 0.25%"><div style="max-width:100%"><div aria-owns="rmiz-modal-" data-rmiz=""><div data-rmiz-content="not-found" style="visibility:visible"><picture><source srcset="/miniblog/blog-img/jxlvother/plots-jxl//raw.jxl" type="image/jxl"><img src="https://saklistudio.com/miniblog/blog-img/jxlvother/plots-jxl//raw.png" alt=""></picture></div></div></div><figcaption style="text-align:center;font-style:italic">RAW ref.</figcaption></figure><figure style="max-width:49%;margin:8px 0.25%"><div style="max-width:100%"><div aria-owns="rmiz-modal-" data-rmiz=""><div data-rmiz-content="not-found" style="visibility:visible"><picture><source srcset="/miniblog/blog-img/jxlvother/plots-jxl/1bpp/jxl-1.048bpp.jxl" type="image/jxl"><img src="https://saklistudio.com/miniblog/blog-img/jxlvother/plots-jxl/1bpp/jxl-1.048bpp.png" alt=""></picture></div></div></div><figcaption style="text-align:center;font-style:italic">JPEG XL ~1.048bpp</figcaption></figure><figure style="max-width:49%;margin:8px 0.25%"><div style="max-width:100%"><div aria-owns="rmiz-modal-" data-rmiz=""><div data-rmiz-content="not-found" style="visibility:visible"><picture><source srcset="/miniblog/blog-img/jxlvother/plots-jxl/1bpp/avif-1.155bpp.jxl" type="image/jxl"><img src="https://saklistudio.com/miniblog/blog-img/jxlvother/plots-jxl/1bpp/avif-1.155bpp.png" alt=""></picture></div></div></div><figcaption style="text-align:center;font-style:italic">AVIF ~1.155bpp</figcaption></figure><figure style="max-width:49%;margin:8px 0.25%"><div style="max-width:100%"><div aria-owns="rmiz-modal-" data-rmiz=""><div data-rmiz-content="not-found" style="visibility:visible"><picture><source srcset="/miniblog/blog-img/jxlvother/plots-jxl/1bpp/webp-1.114bpp.jxl" type="image/jxl"><img src="https://saklistudio.com/miniblog/blog-img/jxlvother/plots-jxl/1bpp/webp-1.114bpp.png" alt=""></picture></div></div></div><figcaption style="text-align:center;font-style:italic">WebP ~1.114bpp</figcaption></figure></div>
<p>Other than WebP limitation (8bpc) that shows a severe quantization errors, the color plot looks pretty similar. I don't see a discernible shift in color for both JPEG XL and AVIF. However AVIF does seems to clump colors even more, seems like smoothing out the noises? Let's dig more...</p>
<h3 class="anchor anchorWithStickyNavbar_LWe7" id="distribution-plot">Distribution Plot<a class="hash-link" aria-label="Direct link to Distribution Plot" title="Direct link to Distribution Plot" href="https://saklistudio.com/miniblog/modern-image-format-linear-color-analysis#distribution-plot">​</a></h3>
<div style="display:flex;flex-flow:wrap;max-width:100%;margin:16px 0;justify-content:center"><figure style="max-width:49%;margin:8px 0.25%"><div style="max-width:100%"><div aria-owns="rmiz-modal-" data-rmiz=""><div data-rmiz-content="not-found" style="visibility:visible"><picture><source srcset="/miniblog/blog-img/jxlvother/plots-jxl//raw-distrib.jxl" type="image/jxl"><img src="https://saklistudio.com/miniblog/blog-img/jxlvother/plots-jxl//raw-distrib.png" alt=""></picture></div></div></div><figcaption style="text-align:center;font-style:italic">RAW ref.</figcaption></figure><figure style="max-width:49%;margin:8px 0.25%"><div style="max-width:100%"><div aria-owns="rmiz-modal-" data-rmiz=""><div data-rmiz-content="not-found" style="visibility:visible"><picture><source srcset="/miniblog/blog-img/jxlvother/plots-jxl/1bpp/jxl-1.048bpp-dist.jxl" type="image/jxl"><img src="https://saklistudio.com/miniblog/blog-img/jxlvother/plots-jxl/1bpp/jxl-1.048bpp-dist.png" alt=""></picture></div></div></div><figcaption style="text-align:center;font-style:italic">JPEG XL ~1.048bpp</figcaption></figure><figure style="max-width:49%;margin:8px 0.25%"><div style="max-width:100%"><div aria-owns="rmiz-modal-" data-rmiz=""><div data-rmiz-content="not-found" style="visibility:visible"><picture><source srcset="/miniblog/blog-img/jxlvother/plots-jxl/1bpp/avif-1.155bpp-dist.jxl" type="image/jxl"><img src="https://saklistudio.com/miniblog/blog-img/jxlvother/plots-jxl/1bpp/avif-1.155bpp-dist.png" alt=""></picture></div></div></div><figcaption style="text-align:center;font-style:italic">AVIF ~1.155bpp</figcaption></figure><figure style="max-width:49%;margin:8px 0.25%"><div style="max-width:100%"><div aria-owns="rmiz-modal-" data-rmiz=""><div data-rmiz-content="not-found" style="visibility:visible"><picture><source srcset="/miniblog/blog-img/jxlvother/plots-jxl/1bpp/webp-1.114bpp-dist.jxl" type="image/jxl"><img src="https://saklistudio.com/miniblog/blog-img/jxlvother/plots-jxl/1bpp/webp-1.114bpp-dist.png" alt=""></picture></div></div></div><figcaption style="text-align:center;font-style:italic">WebP ~1.114bpp</figcaption></figure></div>
<p>We can see how 8bpp (WebP) is barely even suitable for wide-gamut and HDR, only <code>46,214</code> colors remain... Other than that, JPEG XL seems to be doing quite well at preserving the color distribution, it has a total unique color count of <code>4,377,184</code>. On the other hand, AVIF is showing a smudge in color distribution, a slight quantization errors around neutral colors, and having a much smaller unique color count (<code>1,581,283</code>), either due to lower precision (12bpc) or it's indeed softening the colors more.</p>
<h3 class="anchor anchorWithStickyNavbar_LWe7" id="close-up-crops--result-images">Close Up Crops &amp; Result Images<a class="hash-link" aria-label="Direct link to Close Up Crops &amp; Result Images" title="Direct link to Close Up Crops &amp; Result Images" href="https://saklistudio.com/miniblog/modern-image-format-linear-color-analysis#close-up-crops--result-images">​</a></h3>
<p>A plot may look cool and such, but how will it differ visually? Here goes a crop to compare:</p>
<div style="display:flex;flex-flow:wrap;max-width:100%;margin:16px 0;justify-content:center"><figure><div style="max-width:100%"><div aria-owns="rmiz-modal-" data-rmiz=""><div data-rmiz-content="not-found" style="visibility:visible"><picture><source srcset="/miniblog/blog-img/jxlvother/1bpp-anim.jxl" type="image/jxl"><img src="https://saklistudio.com/miniblog/blog-img/jxlvother/1bpp-anim.webp" alt=""></picture></div></div></div><figcaption style="text-align:center;font-style:italic">~1bpp comparison Animation<br>This has been converted to 8bpc sRGB for viewing compatibility</figcaption></figure></div>
<p>Here we can see AVIF got quite a lot of smoothing especially on dark areas, and WebP is starting to look like a blocky mess. While JPEG XL holds quite well maintaining color accuracy and textures.</p>
<p>And these are individual result images:</p>
<div style="display:flex;flex-flow:wrap;max-width:100%;margin:16px 0;justify-content:center"><figure style="max-width:20%;margin:8px 4px"><div aria-owns="rmiz-modal-" data-rmiz=""><div data-rmiz-content="not-found" style="visibility:visible"><img src="https://saklistudio.com/miniblog/blog-img/jxlvother/1bpp-showdown/cjxl-d1.375-1.048bpp.jxl" alt="JPEG XL ~1.048bpp"></div></div><figcaption style="text-align:center;font-style:italic"><a href="https://saklistudio.com/miniblog/assets/files/cjxl-d1.375-1.048bpp-80ec3a0172793675ebb81be39519da20.jxl" target="_blank">JPEG XL ~1.048bpp</a></figcaption></figure><figure style="max-width:20%;margin:8px 4px"><div aria-owns="rmiz-modal-" data-rmiz=""><div data-rmiz-content="not-found" style="visibility:visible"><img src="https://saklistudio.com/miniblog/blog-img/jxlvother/1bpp-showdown/avif-1.155bpp.avif" alt="AVIF ~1.155bpp"></div></div><figcaption style="text-align:center;font-style:italic"><a href="https://saklistudio.com/miniblog/assets/files/avif-1.155bpp-5691135a8676ee2f8e79a7eff20e602f.avif" target="_blank">AVIF ~1.155bpp</a></figcaption></figure><figure style="max-width:20%;margin:8px 4px"><div aria-owns="rmiz-modal-" data-rmiz=""><div data-rmiz-content="not-found" style="visibility:visible"><img src="https://saklistudio.com/miniblog/blog-img/jxlvother/1bpp-showdown/webp-1.114bpp.webp" alt="WebP ~1.114bpp"></div></div><figcaption style="text-align:center;font-style:italic"><a href="https://saklistudio.com/miniblog/assets/files/webp-1.114bpp-c6ec2d3ddfe7ea14df2d0086a39c8f1b.webp" target="_blank">WebP ~1.114bpp</a></figcaption></figure></div>
<p>However, you may notice that these result images may look different than the crop image above that I've been converted into sRGB, since these result images are still in Linear ProPhoto RGB profile and may render differently depends on the browser. Ideally, these images should look all the same in a properly color managed browsers.</p>
<hr>
<h2 class="anchor anchorWithStickyNavbar_LWe7" id="comparison-at-06bpp">Comparison At ~0.6bpp<a class="hash-link" aria-label="Direct link to Comparison At ~0.6bpp" title="Direct link to Comparison At ~0.6bpp" href="https://saklistudio.com/miniblog/modern-image-format-linear-color-analysis#comparison-at-06bpp">​</a></h2>
<p>Few benchmarks that I saw show that AVIF works quite well in low bpp settings. Let's see how it fares in this worse scenario.</p>
<h3 class="anchor anchorWithStickyNavbar_LWe7" id="color-plot-1">Color Plot<a class="hash-link" aria-label="Direct link to Color Plot" title="Direct link to Color Plot" href="https://saklistudio.com/miniblog/modern-image-format-linear-color-analysis#color-plot-1">​</a></h3>
<div style="display:flex;flex-flow:wrap;max-width:100%;margin:16px 0;justify-content:center"><figure style="max-width:49%;margin:8px 0.25%"><div style="max-width:100%"><div aria-owns="rmiz-modal-" data-rmiz=""><div data-rmiz-content="not-found" style="visibility:visible"><picture><source srcset="/miniblog/blog-img/jxlvother/plots-jxl//raw.jxl" type="image/jxl"><img src="https://saklistudio.com/miniblog/blog-img/jxlvother/plots-jxl//raw.png" alt=""></picture></div></div></div><figcaption style="text-align:center;font-style:italic">RAW ref.</figcaption></figure><figure style="max-width:49%;margin:8px 0.25%"><div style="max-width:100%"><div aria-owns="rmiz-modal-" data-rmiz=""><div data-rmiz-content="not-found" style="visibility:visible"><picture><source srcset="/miniblog/blog-img/jxlvother/plots-jxl/0.6bpp/jxl-0.600bpp.jxl" type="image/jxl"><img src="https://saklistudio.com/miniblog/blog-img/jxlvother/plots-jxl/0.6bpp/jxl-0.600bpp.png" alt=""></picture></div></div></div><figcaption style="text-align:center;font-style:italic">JPEG XL ~0.600bpp</figcaption></figure><figure style="max-width:49%;margin:8px 0.25%"><div style="max-width:100%"><div aria-owns="rmiz-modal-" data-rmiz=""><div data-rmiz-content="not-found" style="visibility:visible"><picture><source srcset="/miniblog/blog-img/jxlvother/plots-jxl/0.6bpp/avif-0.617bpp.jxl" type="image/jxl"><img src="https://saklistudio.com/miniblog/blog-img/jxlvother/plots-jxl/0.6bpp/avif-0.617bpp.png" alt=""></picture></div></div></div><figcaption style="text-align:center;font-style:italic">AVIF ~0.617bpp</figcaption></figure><figure style="max-width:49%;margin:8px 0.25%"><div style="max-width:100%"><div aria-owns="rmiz-modal-" data-rmiz=""><div data-rmiz-content="not-found" style="visibility:visible"><picture><source srcset="/miniblog/blog-img/jxlvother/plots-jxl/0.6bpp/webp-0.618bpp.jxl" type="image/jxl"><img src="https://saklistudio.com/miniblog/blog-img/jxlvother/plots-jxl/0.6bpp/webp-0.618bpp.png" alt=""></picture></div></div></div><figcaption style="text-align:center;font-style:italic">WebP ~0.618bpp</figcaption></figure></div>
<p>Lowering the quality further, both JPEG XL and AVIF shows that they narrowing the color spreads even more, indicating more noise smoothing I presume? While JPEG XL mostly have proportional reductions in this perceptual Oklab space, AVIF have some colors squished unproportionally, can be seen noticeably in that green and blue patches. I'm not sure how it implies to the overall color accuracy, but the median point of those color patches on both JPEG XL and AVIF didn't seem to change significantly. <em>And let's ignore WebP result...</em></p>
<h3 class="anchor anchorWithStickyNavbar_LWe7" id="distribution-plot-1">Distribution Plot<a class="hash-link" aria-label="Direct link to Distribution Plot" title="Direct link to Distribution Plot" href="https://saklistudio.com/miniblog/modern-image-format-linear-color-analysis#distribution-plot-1">​</a></h3>
<div style="display:flex;flex-flow:wrap;max-width:100%;margin:16px 0;justify-content:center"><figure style="max-width:49%;margin:8px 0.25%"><div style="max-width:100%"><div aria-owns="rmiz-modal-" data-rmiz=""><div data-rmiz-content="not-found" style="visibility:visible"><picture><source srcset="/miniblog/blog-img/jxlvother/plots-jxl//raw-distrib.jxl" type="image/jxl"><img src="https://saklistudio.com/miniblog/blog-img/jxlvother/plots-jxl//raw-distrib.png" alt=""></picture></div></div></div><figcaption style="text-align:center;font-style:italic">RAW ref.</figcaption></figure><figure style="max-width:49%;margin:8px 0.25%"><div style="max-width:100%"><div aria-owns="rmiz-modal-" data-rmiz=""><div data-rmiz-content="not-found" style="visibility:visible"><picture><source srcset="/miniblog/blog-img/jxlvother/plots-jxl/0.6bpp/jxl-0.600bpp-dist.jxl" type="image/jxl"><img src="https://saklistudio.com/miniblog/blog-img/jxlvother/plots-jxl/0.6bpp/jxl-0.600bpp-dist.png" alt=""></picture></div></div></div><figcaption style="text-align:center;font-style:italic">JPEG XL ~0.600bpp</figcaption></figure><figure style="max-width:49%;margin:8px 0.25%"><div style="max-width:100%"><div aria-owns="rmiz-modal-" data-rmiz=""><div data-rmiz-content="not-found" style="visibility:visible"><picture><source srcset="/miniblog/blog-img/jxlvother/plots-jxl/0.6bpp/avif-0.617bpp-dist.jxl" type="image/jxl"><img src="https://saklistudio.com/miniblog/blog-img/jxlvother/plots-jxl/0.6bpp/avif-0.617bpp-dist.png" alt=""></picture></div></div></div><figcaption style="text-align:center;font-style:italic">AVIF ~0.617bpp</figcaption></figure><figure style="max-width:49%;margin:8px 0.25%"><div style="max-width:100%"><div aria-owns="rmiz-modal-" data-rmiz=""><div data-rmiz-content="not-found" style="visibility:visible"><picture><source srcset="/miniblog/blog-img/jxlvother/plots-jxl/0.6bpp/webp-0.618bpp-dist.jxl" type="image/jxl"><img src="https://saklistudio.com/miniblog/blog-img/jxlvother/plots-jxl/0.6bpp/webp-0.618bpp-dist.png" alt=""></picture></div></div></div><figcaption style="text-align:center;font-style:italic">WebP ~0.618bpp</figcaption></figure></div>
<p>JPEG XL still holds quite well at 0.6bpp, clocking in at <code>4,373,618</code> total unique colors, it didn't seem to differ much from 1bpp result. AVIF shows more prominent quantization errors compared to 1bpp result and seems to 'bleed' the colors even more now, clocking at <code>1,246,309</code> total unique colors, an apparent reduction from 1bpp result.</p>
<h3 class="anchor anchorWithStickyNavbar_LWe7" id="bonus-jpeg-06bpp">Bonus: JPEG ~0.6bpp<a class="hash-link" aria-label="Direct link to Bonus: JPEG ~0.6bpp" title="Direct link to Bonus: JPEG ~0.6bpp" href="https://saklistudio.com/miniblog/modern-image-format-linear-color-analysis#bonus-jpeg-06bpp">​</a></h3>
<div style="display:flex;flex-flow:wrap;max-width:100%;margin:16px 0;justify-content:center"><figure style="max-width:49%;margin:8px 0.25%"><div style="max-width:100%"><div aria-owns="rmiz-modal-" data-rmiz=""><div data-rmiz-content="not-found" style="visibility:visible"><picture><source srcset="/miniblog/blog-img/jxlvother/plots-jxl/0.6bpp/jpeg-0.605bpp.jxl" type="image/jxl"><img src="https://saklistudio.com/miniblog/blog-img/jxlvother/plots-jxl/0.6bpp/jpeg-0.605bpp.png" alt=""></picture></div></div></div><figcaption style="text-align:center;font-style:italic">JPEG ~0.605bpp</figcaption></figure><figure style="max-width:49%;margin:8px 0.25%"><div style="max-width:100%"><div aria-owns="rmiz-modal-" data-rmiz=""><div data-rmiz-content="not-found" style="visibility:visible"><picture><source srcset="/miniblog/blog-img/jxlvother/plots-jxl/0.6bpp/jpeg-0.605bpp-dist.jxl" type="image/jxl"><img src="https://saklistudio.com/miniblog/blog-img/jxlvother/plots-jxl/0.6bpp/jpeg-0.605bpp-dist.png" alt=""></picture></div></div></div><figcaption style="text-align:center;font-style:italic">JPEG ~0.605bpp - distribution</figcaption></figure></div>
<p>Mmm, look at that beautiful-yet-nasty 8-bit quantization~ Even so, they still have much more color than WebP! (<code>84,809</code>)</p>
<h3 class="anchor anchorWithStickyNavbar_LWe7" id="close-up-crops--result-images-1">Close Up Crops &amp; Result Images<a class="hash-link" aria-label="Direct link to Close Up Crops &amp; Result Images" title="Direct link to Close Up Crops &amp; Result Images" href="https://saklistudio.com/miniblog/modern-image-format-linear-color-analysis#close-up-crops--result-images-1">​</a></h3>
<div style="display:flex;flex-flow:wrap;max-width:100%;margin:16px 0;justify-content:center"><figure><div style="max-width:100%"><div aria-owns="rmiz-modal-" data-rmiz=""><div data-rmiz-content="not-found" style="visibility:visible"><picture><source srcset="/miniblog/blog-img/jxlvother/06bpp-anim.jxl" type="image/jxl"><img src="https://saklistudio.com/miniblog/blog-img/jxlvother/06bpp-anim.webp" alt=""></picture></div></div></div><figcaption style="text-align:center;font-style:italic">~06bpp comparison Animation<br>This has been converted to 8bpc sRGB for viewing compatibility</figcaption></figure></div>
<p>In high contrast textures, all formats still performs well to retain the details. But on the low contrast and dark areas, only JPEG XL that can retain the details well. AVIF smooth out almost everything, and most of the color patches are now almost textureless blob of color. While WebP and JPEG is a whole blocky mess now.</p>
<p>And these are individual result images:</p>
<div style="display:flex;flex-flow:wrap;max-width:100%;margin:16px 0;justify-content:center"><figure style="max-width:20%;margin:8px 4px"><div aria-owns="rmiz-modal-" data-rmiz=""><div data-rmiz-content="not-found" style="visibility:visible"><img src="https://saklistudio.com/miniblog/blog-img/jxlvother/06bpp-showdown/cjxl-d2.336-0.600bpp.jxl" alt="JPEG XL ~0.600bpp"></div></div><figcaption style="text-align:center;font-style:italic"><a href="https://saklistudio.com/miniblog/assets/files/cjxl-d2.336-0.600bpp-b4add08b58003ec5f55ed12dec21335f.jxl" target="_blank">JPEG XL ~0.600bpp</a></figcaption></figure><figure style="max-width:20%;margin:8px 4px"><div aria-owns="rmiz-modal-" data-rmiz=""><div data-rmiz-content="not-found" style="visibility:visible"><img src="https://saklistudio.com/miniblog/blog-img/jxlvother/06bpp-showdown/avif-0.617bpp.avif" alt="AVIF ~0.617bpp"></div></div><figcaption style="text-align:center;font-style:italic"><a href="https://saklistudio.com/miniblog/assets/files/avif-0.617bpp-b7d72481ffe60d0696f1ceacc90c2029.avif" target="_blank">AVIF ~0.617bpp</a></figcaption></figure><figure style="max-width:20%;margin:8px 4px"><div aria-owns="rmiz-modal-" data-rmiz=""><div data-rmiz-content="not-found" style="visibility:visible"><img src="https://saklistudio.com/miniblog/blog-img/jxlvother/06bpp-showdown/webp-0.618bpp.webp" alt="WebP ~0.618bpp"></div></div><figcaption style="text-align:center;font-style:italic"><a href="https://saklistudio.com/miniblog/assets/files/webp-0.618bpp-99f40e3e295d1c62fc9f1d9c2eb2e4a8.webp" target="_blank">WebP ~0.618bpp</a></figcaption></figure><figure style="max-width:20%;margin:8px 4px"><div aria-owns="rmiz-modal-" data-rmiz=""><div data-rmiz-content="not-found" style="visibility:visible"><img src="https://saklistudio.com/miniblog/blog-img/jxlvother/06bpp-showdown/jpeg-0.605bpp.jpg" alt="JPEG ~0.605bpp"></div></div><figcaption style="text-align:center;font-style:italic"><a href="https://saklistudio.com/miniblog/assets/files/jpeg-0.605bpp-7ed867658562ab0bd88bf0d55863bc35.jpg" target="_blank">JPEG ~0.605bpp</a></figcaption></figure></div>
<p>However, you may notice that these result images may look different than the crop image above that I've been converted into sRGB, since these result images are still in Linear ProPhoto RGB profile and may render differently depends on the browser. Ideally, these images should look all the same in a properly color managed browsers.</p>
<hr>
<h2 class="anchor anchorWithStickyNavbar_LWe7" id="conclusion">Conclusion<a class="hash-link" aria-label="Direct link to Conclusion" title="Direct link to Conclusion" href="https://saklistudio.com/miniblog/modern-image-format-linear-color-analysis#conclusion">​</a></h2>
<p>Both JPEG XL and AVIF perform quite well on retaining color accuracy, but JPEG XL is absolutely have an edge for this scenario, barely losing any details even though it was given a wide-gamut, linear color profile. It's always a pleasure to see image codec / format with great color profile awareness!</p>
<p>Now, I might say that this is an 'unideal' scenario. But how long 8bpc sRGB will stand as an 'optimal' profile and bit depth? Yes, while linear TRC/gamma might not a good idea for web delivery, but as I said before that consumer HDR display is already here, with all confusing standards to choose from (PQ, HLG, etc.), it's beneficial to have an image format that can still compress wide-gamut spaces and/or various TRC/gamma efficiently. And in lossy JPEG XL case, it's even less likely to be bothered by input image's bit depth, since it already store the compressed pixel data in 32-bit float (XYB) internally.</p>
<!-- -->
<!-- -->
<!-- -->
<hr>
<div class="theme-admonition theme-admonition-note admonition_xJq3 alert alert--secondary"><div class="admonitionHeading_Gvgb"><span class="admonitionIcon_Rf37"><svg viewBox="0 0 14 16"><path fill-rule="evenodd" d="M6.3 5.69a.942.942 0 0 1-.28-.7c0-.28.09-.52.28-.7.19-.18.42-.28.7-.28.28 0 .52.09.7.28.18.19.28.42.28.7 0 .28-.09.52-.28.7a1 1 0 0 1-.7.3c-.28 0-.52-.11-.7-.3zM8 7.99c-.02-.25-.11-.48-.31-.69-.2-.19-.42-.3-.69-.31H6c-.27.02-.48.13-.69.31-.2.2-.3.44-.31.69h1v3c.02.27.11.5.31.69.2.2.42.31.69.31h1c.27 0 .48-.11.69-.31.2-.19.3-.42.31-.69H8V7.98v.01zM7 2.3c-3.14 0-5.7 2.54-5.7 5.68 0 3.14 2.56 5.7 5.7 5.7s5.7-2.55 5.7-5.7c0-3.15-2.56-5.69-5.7-5.69v.01zM7 .98c3.86 0 7 3.14 7 7s-3.14 7-7 7-7-3.12-7-7 3.14-7 7-7z"></path></svg></span>note</div><div class="admonitionContent_BuS1"><p>Just saying this disclaimer once again, I'm just an amateur color enthusiast with quite limited scientific knowledge about color science and human visual. Therefore, this article might have some errors in both writing and testing methodology. If you found some (errors), don't hesitate to <a href="https://saklistudio.com/contactme" target="_blank" rel="noopener noreferrer">poke me</a>!</p></div></div>]]></content>
        <author>
            <name>Kampidh</name>
            <uri>https://saklistudio.com</uri>
        </author>
        <category label="JPEG XL" term="JPEG XL"/>
        <category label="AVIF" term="AVIF"/>
        <category label="WebP" term="WebP"/>
        <category label="Color analysis" term="Color analysis"/>
        <category label="JPEG XL fallback" term="JPEG XL fallback"/>
    </entry>
    <entry>
        <title type="html"><![CDATA[PSO2NGS Pink CAST Dragon Showcase]]></title>
        <id>https://saklistudio.com/miniblog/pso2-pink-dragon-cast-showcase</id>
        <link href="https://saklistudio.com/miniblog/pso2-pink-dragon-cast-showcase"/>
        <updated>2024-05-06T11:28:00.000Z</updated>
        <summary type="html"><![CDATA[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!]]></summary>
        <content type="html"><![CDATA[
<p>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!</p>
<p>Supposed to be a wingless dragon, but the mask made it more like a dragon-fox hybrid.</p>
<h3 class="anchor anchorWithStickyNavbar_LWe7" id="parts-used">Parts Used<a class="hash-link" aria-label="Direct link to Parts Used" title="Direct link to Parts Used" href="https://saklistudio.com/miniblog/pso2-pink-dragon-cast-showcase#parts-used">​</a></h3>
<p>Here's the main parts list:</p>
<ul>
<li><strong>Body</strong>: Gerifalte Body<!-- -->
<ul>
<li><em>one of the few fully-armored T2 body</em> 💗</li>
</ul>
</li>
<li><strong>Arms</strong>: Krolik Arms/B</li>
<li><strong>Legs</strong>: N-Amuaira Legs V2</li>
<li><strong>Head</strong>: Moonlight Hair/D</li>
</ul>
<p>Accessories:</p>
<ul>
<li><strong>Head</strong>: Sylphos Mask, Rithia Hair Ornament, Cat Eye Contacts</li>
<li><strong>Others</strong>: MC96 Field Walker, Mechanical Fin/B, Dinorex Tail</li>
</ul>
<p>Let's start the showcase then! :3</p>
<div style="max-width:100%"><div aria-owns="rmiz-modal-" data-rmiz=""><div data-rmiz-content="not-found" style="visibility:visible"><picture><source srcset="/miniblog/blog-img/pinkcastdreg/pinkcastdreg-18.jxl" type="image/jxl"><img src="https://saklistudio.com/miniblog/blog-img/pinkcastdreg/pinkcastdreg-18.jpg" alt=""></picture></div></div></div>
<!-- -->
<div style="display:flex;flex-flow:wrap;max-width:100%"><div style="max-width:100%"><div aria-owns="rmiz-modal-" data-rmiz=""><div data-rmiz-content="not-found" style="visibility:visible"><picture><source srcset="/miniblog/blog-img/pinkcastdreg/pinkcastdreg-01.jxl" type="image/jxl"><img src="https://saklistudio.com/miniblog/blog-img/pinkcastdreg/pinkcastdreg-01.jpg" alt=""></picture></div></div></div><div style="max-width:100%"><div aria-owns="rmiz-modal-" data-rmiz=""><div data-rmiz-content="not-found" style="visibility:visible"><picture><source srcset="/miniblog/blog-img/pinkcastdreg/pinkcastdreg-13.jxl" type="image/jxl"><img src="https://saklistudio.com/miniblog/blog-img/pinkcastdreg/pinkcastdreg-13.jpg" alt=""></picture></div></div></div><div style="max-width:100%"><div aria-owns="rmiz-modal-" data-rmiz=""><div data-rmiz-content="not-found" style="visibility:visible"><picture><source srcset="/miniblog/blog-img/pinkcastdreg/pinkcastdreg-14.jxl" type="image/jxl"><img src="https://saklistudio.com/miniblog/blog-img/pinkcastdreg/pinkcastdreg-14.jpg" alt=""></picture></div></div></div><div style="max-width:100%"><div aria-owns="rmiz-modal-" data-rmiz=""><div data-rmiz-content="not-found" style="visibility:visible"><picture><source srcset="/miniblog/blog-img/pinkcastdreg/pinkcastdreg-15.jxl" type="image/jxl"><img src="https://saklistudio.com/miniblog/blog-img/pinkcastdreg/pinkcastdreg-15.jpg" alt=""></picture></div></div></div><div style="max-width:100%"><div aria-owns="rmiz-modal-" data-rmiz=""><div data-rmiz-content="not-found" style="visibility:visible"><picture><source srcset="/miniblog/blog-img/pinkcastdreg/pinkcastdreg-16.jxl" type="image/jxl"><img src="https://saklistudio.com/miniblog/blog-img/pinkcastdreg/pinkcastdreg-16.jpg" alt=""></picture></div></div></div><div style="max-width:100%"><div aria-owns="rmiz-modal-" data-rmiz=""><div data-rmiz-content="not-found" style="visibility:visible"><picture><source srcset="/miniblog/blog-img/pinkcastdreg/pinkcastdreg-19.jxl" type="image/jxl"><img src="https://saklistudio.com/miniblog/blog-img/pinkcastdreg/pinkcastdreg-19.jpg" alt=""></picture></div></div></div><div style="max-width:100%"><div aria-owns="rmiz-modal-" data-rmiz=""><div data-rmiz-content="not-found" style="visibility:visible"><picture><source srcset="/miniblog/blog-img/pinkcastdreg/pinkcastdreg-20.jxl" type="image/jxl"><img src="https://saklistudio.com/miniblog/blog-img/pinkcastdreg/pinkcastdreg-20.jpg" alt=""></picture></div></div></div><div style="max-width:100%"><div aria-owns="rmiz-modal-" data-rmiz=""><div data-rmiz-content="not-found" style="visibility:visible"><picture><source srcset="/miniblog/blog-img/pinkcastdreg/pinkcastdreg-23.jxl" type="image/jxl"><img src="https://saklistudio.com/miniblog/blog-img/pinkcastdreg/pinkcastdreg-23.jpg" alt=""></picture></div></div></div><div style="max-width:100%"><div aria-owns="rmiz-modal-" data-rmiz=""><div data-rmiz-content="not-found" style="visibility:visible"><picture><source srcset="/miniblog/blog-img/pinkcastdreg/pinkcastdreg-25.jxl" type="image/jxl"><img src="https://saklistudio.com/miniblog/blog-img/pinkcastdreg/pinkcastdreg-25.jpg" alt=""></picture></div></div></div><div style="max-width:49%;margin:0.25% 0.5%"><div aria-owns="rmiz-modal-" data-rmiz=""><div data-rmiz-content="not-found" style="visibility:visible"><picture><source srcset="/miniblog/blog-img/pinkcastdreg/pinkcastdreg-03.jxl" type="image/jxl"><img src="https://saklistudio.com/miniblog/blog-img/pinkcastdreg/pinkcastdreg-03.jpg" alt=""></picture></div></div></div><div style="max-width:49%;margin:0.25% 0.5%"><div aria-owns="rmiz-modal-" data-rmiz=""><div data-rmiz-content="not-found" style="visibility:visible"><picture><source srcset="/miniblog/blog-img/pinkcastdreg/pinkcastdreg-12.jxl" type="image/jxl"><img src="https://saklistudio.com/miniblog/blog-img/pinkcastdreg/pinkcastdreg-12.jpg" alt=""></picture></div></div></div><div style="max-width:49%;margin:0.25% 0.5%"><div aria-owns="rmiz-modal-" data-rmiz=""><div data-rmiz-content="not-found" style="visibility:visible"><picture><source srcset="/miniblog/blog-img/pinkcastdreg/pinkcastdreg-17.jxl" type="image/jxl"><img src="https://saklistudio.com/miniblog/blog-img/pinkcastdreg/pinkcastdreg-17.jpg" alt=""></picture></div></div></div><div style="max-width:49%;margin:0.25% 0.5%"><div aria-owns="rmiz-modal-" data-rmiz=""><div data-rmiz-content="not-found" style="visibility:visible"><picture><source srcset="/miniblog/blog-img/pinkcastdreg/pinkcastdreg-26.jxl" type="image/jxl"><img src="https://saklistudio.com/miniblog/blog-img/pinkcastdreg/pinkcastdreg-26.jpg" alt=""></picture></div></div></div></div>
<h3 class="anchor anchorWithStickyNavbar_LWe7" id="alternate-version-with-theanaga-hair">Alternate version with Theanaga Hair<a class="hash-link" aria-label="Direct link to Alternate version with Theanaga Hair" title="Direct link to Alternate version with Theanaga Hair" href="https://saklistudio.com/miniblog/pso2-pink-dragon-cast-showcase#alternate-version-with-theanaga-hair">​</a></h3>
<p>I love this looks too, but that long hair kinda hide the body's silhouette...</p>
<div style="display:flex;flex-flow:wrap;max-width:100%"><div style="max-width:100%"><div aria-owns="rmiz-modal-" data-rmiz=""><div data-rmiz-content="not-found" style="visibility:visible"><picture><source srcset="/miniblog/blog-img/pinkcastdreg/pinkcastdreg-07.jxl" type="image/jxl"><img src="https://saklistudio.com/miniblog/blog-img/pinkcastdreg/pinkcastdreg-07.jpg" alt=""></picture></div></div></div><div style="max-width:49%;margin:0.25% 0.5%"><div aria-owns="rmiz-modal-" data-rmiz=""><div data-rmiz-content="not-found" style="visibility:visible"><picture><source srcset="/miniblog/blog-img/pinkcastdreg/pinkcastdreg-11.jxl" type="image/jxl"><img src="https://saklistudio.com/miniblog/blog-img/pinkcastdreg/pinkcastdreg-11.jpg" alt=""></picture></div></div></div><div style="max-width:49%;margin:0.25% 0.5%"><div aria-owns="rmiz-modal-" data-rmiz=""><div data-rmiz-content="not-found" style="visibility:visible"><picture><source srcset="/miniblog/blog-img/pinkcastdreg/pinkcastdreg-08.jxl" type="image/jxl"><img src="https://saklistudio.com/miniblog/blog-img/pinkcastdreg/pinkcastdreg-08.jpg" alt=""></picture></div></div></div><div style="max-width:49%;margin:0.25% 0.5%"><div aria-owns="rmiz-modal-" data-rmiz=""><div data-rmiz-content="not-found" style="visibility:visible"><picture><source srcset="/miniblog/blog-img/pinkcastdreg/pinkcastdreg-09.jxl" type="image/jxl"><img src="https://saklistudio.com/miniblog/blog-img/pinkcastdreg/pinkcastdreg-09.jpg" alt=""></picture></div></div></div><div style="max-width:49%;margin:0.25% 0.5%"><div aria-owns="rmiz-modal-" data-rmiz=""><div data-rmiz-content="not-found" style="visibility:visible"><picture><source srcset="/miniblog/blog-img/pinkcastdreg/pinkcastdreg-10.jxl" type="image/jxl"><img src="https://saklistudio.com/miniblog/blog-img/pinkcastdreg/pinkcastdreg-10.jpg" alt=""></picture></div></div></div></div>
<h3 class="anchor anchorWithStickyNavbar_LWe7" id="alternate-light-armor-version">Alternate light armor version<a class="hash-link" aria-label="Direct link to Alternate light armor version" title="Direct link to Alternate light armor version" href="https://saklistudio.com/miniblog/pso2-pink-dragon-cast-showcase#alternate-light-armor-version">​</a></h3>
<p>"Off-battle" without leg armor and arms part replaced with Moonlight Arms/2, highlighting the N-Amuaira Legs thigh-high wrinkles at its finest!</p>
<div style="display:flex;flex-flow:wrap;max-width:100%"><div style="max-width:49%;margin:0.25% 0.5%"><div aria-owns="rmiz-modal-" data-rmiz=""><div data-rmiz-content="not-found" style="visibility:visible"><picture><source srcset="/miniblog/blog-img/pinkcastdreg/pinkcastdreg-05.jxl" type="image/jxl"><img src="https://saklistudio.com/miniblog/blog-img/pinkcastdreg/pinkcastdreg-05.jpg" alt=""></picture></div></div></div><div style="max-width:49%;margin:0.25% 0.5%"><div aria-owns="rmiz-modal-" data-rmiz=""><div data-rmiz-content="not-found" style="visibility:visible"><picture><source srcset="/miniblog/blog-img/pinkcastdreg/pinkcastdreg-06.jxl" type="image/jxl"><img src="https://saklistudio.com/miniblog/blog-img/pinkcastdreg/pinkcastdreg-06.jpg" alt=""></picture></div></div></div></div>
<h3 class="anchor anchorWithStickyNavbar_LWe7" id="winged-version">Winged version<a class="hash-link" aria-label="Direct link to Winged version" title="Direct link to Winged version" href="https://saklistudio.com/miniblog/pso2-pink-dragon-cast-showcase#winged-version">​</a></h3>
<p>Item: Wing Blades Quatre. Don't really like the silhouette, but still looks pretty cool~ x3</p>
<div style="max-width:49%;margin:0.25% 0.5%"><div aria-owns="rmiz-modal-" data-rmiz=""><div data-rmiz-content="not-found" style="visibility:visible"><picture><source srcset="/miniblog/blog-img/pinkcastdreg/pinkcastdreg-02.jxl" type="image/jxl"><img src="https://saklistudio.com/miniblog/blog-img/pinkcastdreg/pinkcastdreg-02.jpg" alt=""></picture></div></div></div>
<h3 class="anchor anchorWithStickyNavbar_LWe7" id="bonus-absolute-territory">Bonus: Absolute territory<a class="hash-link" aria-label="Direct link to Bonus: Absolute territory" title="Direct link to Bonus: Absolute territory" href="https://saklistudio.com/miniblog/pso2-pink-dragon-cast-showcase#bonus-absolute-territory">​</a></h3>
<p>When cold-hard CAST body meets a soft fabric in a form of thigh-high socks~ Ugh, this is too perfect!! 💗</p>
<div style="display:flex;flex-flow:wrap;max-width:100%"><div style="max-width:100%"><div aria-owns="rmiz-modal-" data-rmiz=""><div data-rmiz-content="not-found" style="visibility:visible"><picture><source srcset="/miniblog/blog-img/pinkcastdreg/pinkcastdreg-24.jxl" type="image/jxl"><img src="https://saklistudio.com/miniblog/blog-img/pinkcastdreg/pinkcastdreg-24.jpg" alt=""></picture></div></div></div><div style="max-width:49%;margin:0.25% 0.5%"><div aria-owns="rmiz-modal-" data-rmiz=""><div data-rmiz-content="not-found" style="visibility:visible"><picture><source srcset="/miniblog/blog-img/pinkcastdreg/pinkcastdreg-21.jxl" type="image/jxl"><img src="https://saklistudio.com/miniblog/blog-img/pinkcastdreg/pinkcastdreg-21.jpg" alt=""></picture></div></div></div><div style="max-width:49%;margin:0.25% 0.5%"><div aria-owns="rmiz-modal-" data-rmiz=""><div data-rmiz-content="not-found" style="visibility:visible"><picture><source srcset="/miniblog/blog-img/pinkcastdreg/pinkcastdreg-22.jxl" type="image/jxl"><img src="https://saklistudio.com/miniblog/blog-img/pinkcastdreg/pinkcastdreg-22.jpg" alt=""></picture></div></div></div><div style="max-width:49%;margin:0.25% 0.5%"><div aria-owns="rmiz-modal-" data-rmiz=""><div data-rmiz-content="not-found" style="visibility:visible"><picture><source srcset="/miniblog/blog-img/pinkcastdreg/pinkcastdreg-04.jxl" type="image/jxl"><img src="https://saklistudio.com/miniblog/blog-img/pinkcastdreg/pinkcastdreg-04.jpg" alt=""></picture></div></div></div><div style="max-width:49%;margin:0.25% 0.5%"><div style="max-width:100%"><div aria-owns="rmiz-modal-" data-rmiz=""><div data-rmiz-content="not-found" style="visibility:visible"><picture><source srcset="/miniblog/blog-img/pinkcastdreg/yabe.jxl" type="image/jxl"><img src="https://saklistudio.com/miniblog/blog-img/pinkcastdreg/yabe.jpg" alt=""></picture></div></div></div><p>*<em>literally me</em></p></div></div>
<hr>
<div class="theme-admonition theme-admonition-note admonition_xJq3 alert alert--secondary"><div class="admonitionHeading_Gvgb"><span class="admonitionIcon_Rf37"><svg viewBox="0 0 14 16"><path fill-rule="evenodd" d="M6.3 5.69a.942.942 0 0 1-.28-.7c0-.28.09-.52.28-.7.19-.18.42-.28.7-.28.28 0 .52.09.7.28.18.19.28.42.28.7 0 .28-.09.52-.28.7a1 1 0 0 1-.7.3c-.28 0-.52-.11-.7-.3zM8 7.99c-.02-.25-.11-.48-.31-.69-.2-.19-.42-.3-.69-.31H6c-.27.02-.48.13-.69.31-.2.2-.3.44-.31.69h1v3c.02.27.11.5.31.69.2.2.42.31.69.31h1c.27 0 .48-.11.69-.31.2-.19.3-.42.31-.69H8V7.98v.01zM7 2.3c-3.14 0-5.7 2.54-5.7 5.68 0 3.14 2.56 5.7 5.7 5.7s5.7-2.55 5.7-5.7c0-3.15-2.56-5.69-5.7-5.69v.01zM7 .98c3.86 0 7 3.14 7 7s-3.14 7-7 7-7-3.12-7-7 3.14-7 7-7z"></path></svg></span>note</div><div class="admonitionContent_BuS1"><p>The images are at full 2.5k res (2560x1440) and served both in JPEG XL and JPG as a falback on unsupported browsers. Using <code>libjxl 0.10.2</code>, both <code>cjxl</code> and <code>cjpegli</code> parameters are d=1.0 / q=90.0, with <code>--xyb</code> option enabled for <code>cjpegli</code> (thus jpg fallback might cause color mismatch when viewed on unmanaged browsers / viewers).</p></div></div>]]></content>
        <author>
            <name>Kisi</name>
            <uri>https://saklistudio.com</uri>
        </author>
        <category label="gaming" term="gaming"/>
        <category label="PSO2NGS" term="PSO2NGS"/>
        <category label="JPEG XL fallback" term="JPEG XL fallback"/>
        <category label="jpegli" term="jpegli"/>
    </entry>
    <entry>
        <title type="html"><![CDATA[PSO2NGS Blue CAST Dragon Showcase]]></title>
        <id>https://saklistudio.com/miniblog/pso2-blue-dragon-cast-showcase</id>
        <link href="https://saklistudio.com/miniblog/pso2-blue-dragon-cast-showcase"/>
        <updated>2024-05-05T14:51:00.000Z</updated>
        <summary type="html"><![CDATA[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!]]></summary>
        <content type="html"><![CDATA[
<p>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!</p>
<p>Ugh, if only we have big claw arms to complete it...</p>
<h3 class="anchor anchorWithStickyNavbar_LWe7" id="parts-used">Parts Used<a class="hash-link" aria-label="Direct link to Parts Used" title="Direct link to Parts Used" href="https://saklistudio.com/miniblog/pso2-blue-dragon-cast-showcase#parts-used">​</a></h3>
<p>Here's the main parts list:</p>
<ul>
<li><strong>Body</strong>: Ruka Body</li>
<li><strong>Arms</strong>: Ruka Arms/B (should have used the normal version to match the grunge...)</li>
<li><strong>Legs</strong>: Dinorex Legs</li>
<li><strong>Head</strong>: Pro Vosse Head</li>
</ul>
<p>Accessories:</p>
<ul>
<li><strong>Head</strong>: Lion Head Shield, Krolik Headgear/B</li>
<li><strong>Others</strong>: Big Robot Shoes/B, Tri Fin Blade, Dinorex Tail</li>
</ul>
<p>Let's start the showcase then! :3</p>
<div style="max-width:100%"><div aria-owns="rmiz-modal-" data-rmiz=""><div data-rmiz-content="not-found" style="visibility:visible"><picture><source srcset="/miniblog/blog-img/bluecastdreg/bluecastdreg-05.jxl" type="image/jxl"><img src="https://saklistudio.com/miniblog/blog-img/bluecastdreg/bluecastdreg-05.jpg" alt=""></picture></div></div></div>
<!-- -->
<div style="display:flex;flex-flow:wrap;max-width:100%"><div style="max-width:100%"><div aria-owns="rmiz-modal-" data-rmiz=""><div data-rmiz-content="not-found" style="visibility:visible"><picture><source srcset="/miniblog/blog-img/bluecastdreg/bluecastdreg-07.jxl" type="image/jxl"><img src="https://saklistudio.com/miniblog/blog-img/bluecastdreg/bluecastdreg-07.jpg" alt=""></picture></div></div></div><div style="max-width:100%"><div aria-owns="rmiz-modal-" data-rmiz=""><div data-rmiz-content="not-found" style="visibility:visible"><picture><source srcset="/miniblog/blog-img/bluecastdreg/bluecastdreg-08.jxl" type="image/jxl"><img src="https://saklistudio.com/miniblog/blog-img/bluecastdreg/bluecastdreg-08.jpg" alt=""></picture></div></div></div><div style="max-width:100%"><div aria-owns="rmiz-modal-" data-rmiz=""><div data-rmiz-content="not-found" style="visibility:visible"><picture><source srcset="/miniblog/blog-img/bluecastdreg/bluecastdreg-09.jxl" type="image/jxl"><img src="https://saklistudio.com/miniblog/blog-img/bluecastdreg/bluecastdreg-09.jpg" alt=""></picture></div></div></div><div style="max-width:100%"><div aria-owns="rmiz-modal-" data-rmiz=""><div data-rmiz-content="not-found" style="visibility:visible"><picture><source srcset="/miniblog/blog-img/bluecastdreg/bluecastdreg-10.jxl" type="image/jxl"><img src="https://saklistudio.com/miniblog/blog-img/bluecastdreg/bluecastdreg-10.jpg" alt=""></picture></div></div></div><div style="max-width:100%"><div aria-owns="rmiz-modal-" data-rmiz=""><div data-rmiz-content="not-found" style="visibility:visible"><picture><source srcset="/miniblog/blog-img/bluecastdreg/bluecastdreg-11.jxl" type="image/jxl"><img src="https://saklistudio.com/miniblog/blog-img/bluecastdreg/bluecastdreg-11.jpg" alt=""></picture></div></div></div><div style="max-width:100%"><div aria-owns="rmiz-modal-" data-rmiz=""><div data-rmiz-content="not-found" style="visibility:visible"><picture><source srcset="/miniblog/blog-img/bluecastdreg/bluecastdreg-12.jxl" type="image/jxl"><img src="https://saklistudio.com/miniblog/blog-img/bluecastdreg/bluecastdreg-12.jpg" alt=""></picture></div></div></div><div style="max-width:100%"><div aria-owns="rmiz-modal-" data-rmiz=""><div data-rmiz-content="not-found" style="visibility:visible"><picture><source srcset="/miniblog/blog-img/bluecastdreg/bluecastdreg-13.jxl" type="image/jxl"><img src="https://saklistudio.com/miniblog/blog-img/bluecastdreg/bluecastdreg-13.jpg" alt=""></picture></div></div></div><div style="max-width:100%"><div aria-owns="rmiz-modal-" data-rmiz=""><div data-rmiz-content="not-found" style="visibility:visible"><picture><source srcset="/miniblog/blog-img/bluecastdreg/bluecastdreg-16.jxl" type="image/jxl"><img src="https://saklistudio.com/miniblog/blog-img/bluecastdreg/bluecastdreg-16.jpg" alt=""></picture></div></div></div><div style="max-width:49%;margin:0.25% 0.5%"><div aria-owns="rmiz-modal-" data-rmiz=""><div data-rmiz-content="not-found" style="visibility:visible"><picture><source srcset="/miniblog/blog-img/bluecastdreg/bluecastdreg-01.jxl" type="image/jxl"><img src="https://saklistudio.com/miniblog/blog-img/bluecastdreg/bluecastdreg-01.jpg" alt=""></picture></div></div></div><div style="max-width:49%;margin:0.25% 0.5%"><div aria-owns="rmiz-modal-" data-rmiz=""><div data-rmiz-content="not-found" style="visibility:visible"><picture><source srcset="/miniblog/blog-img/bluecastdreg/bluecastdreg-02.jxl" type="image/jxl"><img src="https://saklistudio.com/miniblog/blog-img/bluecastdreg/bluecastdreg-02.jpg" alt=""></picture></div></div></div><div style="max-width:49%;margin:0.25% 0.5%"><div aria-owns="rmiz-modal-" data-rmiz=""><div data-rmiz-content="not-found" style="visibility:visible"><picture><source srcset="/miniblog/blog-img/bluecastdreg/bluecastdreg-03.jxl" type="image/jxl"><img src="https://saklistudio.com/miniblog/blog-img/bluecastdreg/bluecastdreg-03.jpg" alt=""></picture></div></div></div><div style="max-width:49%;margin:0.25% 0.5%"><div aria-owns="rmiz-modal-" data-rmiz=""><div data-rmiz-content="not-found" style="visibility:visible"><picture><source srcset="/miniblog/blog-img/bluecastdreg/bluecastdreg-04.jxl" type="image/jxl"><img src="https://saklistudio.com/miniblog/blog-img/bluecastdreg/bluecastdreg-04.jpg" alt=""></picture></div></div></div><div style="max-width:49%;margin:0.25% 0.5%"><div aria-owns="rmiz-modal-" data-rmiz=""><div data-rmiz-content="not-found" style="visibility:visible"><picture><source srcset="/miniblog/blog-img/bluecastdreg/bluecastdreg-06.jxl" type="image/jxl"><img src="https://saklistudio.com/miniblog/blog-img/bluecastdreg/bluecastdreg-06.jpg" alt=""></picture></div></div></div><div style="max-width:49%;margin:0.25% 0.5%"><div aria-owns="rmiz-modal-" data-rmiz=""><div data-rmiz-content="not-found" style="visibility:visible"><picture><source srcset="/miniblog/blog-img/bluecastdreg/bluecastdreg-14.jxl" type="image/jxl"><img src="https://saklistudio.com/miniblog/blog-img/bluecastdreg/bluecastdreg-14.jpg" alt=""></picture></div></div></div><div style="max-width:49%;margin:0.25% 0.5%"><div aria-owns="rmiz-modal-" data-rmiz=""><div data-rmiz-content="not-found" style="visibility:visible"><picture><source srcset="/miniblog/blog-img/bluecastdreg/bluecastdreg-15.jxl" type="image/jxl"><img src="https://saklistudio.com/miniblog/blog-img/bluecastdreg/bluecastdreg-15.jpg" alt=""></picture></div></div></div><div style="max-width:49%;margin:0.25% 0.5%"><div aria-owns="rmiz-modal-" data-rmiz=""><div data-rmiz-content="not-found" style="visibility:visible"><picture><source srcset="/miniblog/blog-img/bluecastdreg/bluecastdreg-17.jxl" type="image/jxl"><img src="https://saklistudio.com/miniblog/blog-img/bluecastdreg/bluecastdreg-17.jpg" alt=""></picture></div></div></div></div>
<hr>
<div class="theme-admonition theme-admonition-note admonition_xJq3 alert alert--secondary"><div class="admonitionHeading_Gvgb"><span class="admonitionIcon_Rf37"><svg viewBox="0 0 14 16"><path fill-rule="evenodd" d="M6.3 5.69a.942.942 0 0 1-.28-.7c0-.28.09-.52.28-.7.19-.18.42-.28.7-.28.28 0 .52.09.7.28.18.19.28.42.28.7 0 .28-.09.52-.28.7a1 1 0 0 1-.7.3c-.28 0-.52-.11-.7-.3zM8 7.99c-.02-.25-.11-.48-.31-.69-.2-.19-.42-.3-.69-.31H6c-.27.02-.48.13-.69.31-.2.2-.3.44-.31.69h1v3c.02.27.11.5.31.69.2.2.42.31.69.31h1c.27 0 .48-.11.69-.31.2-.19.3-.42.31-.69H8V7.98v.01zM7 2.3c-3.14 0-5.7 2.54-5.7 5.68 0 3.14 2.56 5.7 5.7 5.7s5.7-2.55 5.7-5.7c0-3.15-2.56-5.69-5.7-5.69v.01zM7 .98c3.86 0 7 3.14 7 7s-3.14 7-7 7-7-3.12-7-7 3.14-7 7-7z"></path></svg></span>note</div><div class="admonitionContent_BuS1"><p>The images are at full 2.5k res (2560x1440) and served both in JPEG XL and JPG as a falback on unsupported browsers. Using <code>libjxl 0.10.2</code>, both <code>cjxl</code> and <code>cjpegli</code> parameters are d=1.0 / q=90.0, with <code>--xyb</code> option enabled for <code>cjpegli</code> (thus jpg fallback might cause color mismatch when viewed on unmanaged browsers / viewers).</p></div></div>]]></content>
        <author>
            <name>Kisi</name>
            <uri>https://saklistudio.com</uri>
        </author>
        <category label="gaming" term="gaming"/>
        <category label="PSO2NGS" term="PSO2NGS"/>
        <category label="JPEG XL fallback" term="JPEG XL fallback"/>
        <category label="jpegli" term="jpegli"/>
    </entry>
    <entry>
        <title type="html"><![CDATA[Krita 5.2 JPEG XL Export Tips]]></title>
        <id>https://saklistudio.com/miniblog/krita-jpegxl-tips</id>
        <link href="https://saklistudio.com/miniblog/krita-jpegxl-tips"/>
        <updated>2023-10-08T18:03:00.000Z</updated>
        <summary type="html"><![CDATA[Intro]]></summary>
        <content type="html"><![CDATA[<h2 class="anchor anchorWithStickyNavbar_LWe7" id="intro">Intro<a class="hash-link" aria-label="Direct link to Intro" title="Direct link to Intro" href="https://saklistudio.com/miniblog/krita-jpegxl-tips#intro">​</a></h2>
<p>With the release of version 5.2, <a href="https://krita.org/en/krita-5-2-release-notes/" target="_blank" rel="noopener noreferrer">Krita</a> 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</p>
<p>Here I'll try to give some tips to use it efficiently!</p>
<h3 class="anchor anchorWithStickyNavbar_LWe7" id="jpeg-xl">JPEG XL?<a class="hash-link" aria-label="Direct link to JPEG XL?" title="Direct link to JPEG XL?" href="https://saklistudio.com/miniblog/krita-jpegxl-tips#jpeg-xl">​</a></h3>
<p><a href="https://jpegxl.info/" target="_blank" rel="noopener noreferrer">JPEG XL</a> (or JXL for short) is a relatively new image standard by the JPEG committee <em>(yes, the old JPEG that we all familiar with!)</em>. It's aimed to be a long-term replacement for web image delivery formats like the old <strong>JPEG</strong> and <strong>PNG</strong>. It also have basic animation function like <strong>GIF</strong> and <strong>APNG</strong>, 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!</p>
<!-- -->
<div class="theme-admonition theme-admonition-warning admonition_xJq3 alert alert--warning"><div class="admonitionHeading_Gvgb"><span class="admonitionIcon_Rf37"><svg viewBox="0 0 16 16"><path fill-rule="evenodd" d="M8.893 1.5c-.183-.31-.52-.5-.887-.5s-.703.19-.886.5L.138 13.499a.98.98 0 0 0 0 1.001c.193.31.53.501.886.501h13.964c.367 0 .704-.19.877-.5a1.03 1.03 0 0 0 .01-1.002L8.893 1.5zm.133 11.497H6.987v-2.003h2.039v2.003zm0-3.004H6.987V5.987h2.039v4.006z"></path></svg></span>warning</div><div class="admonitionContent_BuS1"><p>Some of the images in this post are served <strong>only</strong> in JPEG XL format, as per iOS/iPadOS 17 or MacOS 14 (Sonoma) Safari already have a native support for viewing JPEG XL images. And for other OSes, I recommend using JPEG XL enabled browsers like <a href="https://www.waterfox.net/" target="_blank" rel="noopener noreferrer">Waterfox</a>.</p></div></div>
<hr>
<h2 class="anchor anchorWithStickyNavbar_LWe7" id="general-export-options-on-krita">General export options on Krita<a class="hash-link" aria-label="Direct link to General export options on Krita" title="Direct link to General export options on Krita" href="https://saklistudio.com/miniblog/krita-jpegxl-tips#general-export-options-on-krita">​</a></h2>
<p>Here's the Krita's export dialog when selecting JPEG XL format:</p>
<div style="max-width:100%"><div aria-owns="rmiz-modal-" data-rmiz=""><div data-rmiz-content="not-found" style="visibility:visible"><picture><source srcset="/miniblog/blog-img/krajxltips/krita-jxl-export-general.jxl" type="image/jxl"><img src="https://saklistudio.com/miniblog/blog-img/krajxltips/krita-jxl-export-general.png" alt="General Tab"></picture></div></div></div>
<p>I'll try to break it down shortly while copying some of the descriptions from <a href="https://docs.krita.org/en/general_concepts/file_formats/file_jxl.html" target="_blank" rel="noopener noreferrer">official docs</a>.</p>
<h3 class="anchor anchorWithStickyNavbar_LWe7" id="1-save-as-animated-jpeg-xl">1. Save as animated JPEG XL<a class="hash-link" aria-label="Direct link to 1. Save as animated JPEG XL" title="Direct link to 1. Save as animated JPEG XL" href="https://saklistudio.com/miniblog/krita-jpegxl-tips#1-save-as-animated-jpeg-xl">​</a></h3>
<p>JPEG XL has the ability to store small animations like <strong>GIF</strong> or <strong>APNG</strong>. This option will save as animated JPEG XL if your canvas has an animation. It is generally safe to left this option enabled even if your canvas is not animated.</p>
<h3 class="anchor anchorWithStickyNavbar_LWe7" id="2-flatten-the-image">2. Flatten the image<a class="hash-link" aria-label="Direct link to 2. Flatten the image" title="Direct link to 2. Flatten the image" href="https://saklistudio.com/miniblog/krita-jpegxl-tips#2-flatten-the-image">​</a></h3>
<p>If disabled, JPEG XL has the ability to store frames as layers if it's not being used as animation, this can be useful to store multi-page images like <strong>TIFF</strong>. Its layered capabilities are very basic, and not designed to store complex layer stacks like <strong>PSD</strong> and <strong>KRA</strong>(native krita file) does. However, this option is mutually exclusive with <strong>Save as animated JPEG XL</strong>, as animated JPEG XL will have the layers flattened. Please refer to the official docs above for detailed limitations!</p>
<p>I don't know what the future will tell, but I recommend to leave this option enabled for web delivery / uploads. ^^</p>
<div class="theme-admonition theme-admonition-note admonition_xJq3 alert alert--secondary"><div class="admonitionHeading_Gvgb"><span class="admonitionIcon_Rf37"><svg viewBox="0 0 14 16"><path fill-rule="evenodd" d="M6.3 5.69a.942.942 0 0 1-.28-.7c0-.28.09-.52.28-.7.19-.18.42-.28.7-.28.28 0 .52.09.7.28.18.19.28.42.28.7 0 .28-.09.52-.28.7a1 1 0 0 1-.7.3c-.28 0-.52-.11-.7-.3zM8 7.99c-.02-.25-.11-.48-.31-.69-.2-.19-.42-.3-.69-.31H6c-.27.02-.48.13-.69.31-.2.2-.3.44-.31.69h1v3c.02.27.11.5.31.69.2.2.42.31.69.31h1c.27 0 .48-.11.69-.31.2-.19.3-.42.31-.69H8V7.98v.01zM7 2.3c-3.14 0-5.7 2.54-5.7 5.68 0 3.14 2.56 5.7 5.7 5.7s5.7-2.55 5.7-5.7c0-3.15-2.56-5.69-5.7-5.69v.01zM7 .98c3.86 0 7 3.14 7 7s-3.14 7-7 7-7-3.12-7-7 3.14-7 7-7z"></path></svg></span>note</div><div class="admonitionContent_BuS1"><p><strong>This example image is on JPEG XL only</strong> and will not visible on browsers without JPEG XL support</p></div></div>
<div aria-owns="rmiz-modal-" data-rmiz=""><div data-rmiz-content="not-found" style="visibility:visible"><img src="https://saklistudio.com/miniblog/blog-img/krajxltips/happy-zephyra.jxl" alt="Happy Zephyra" style="max-width:100%;height:auto"></div></div>
<p><em>Example of multi-layer JPEG XL image, this one contains 6 layers. Try to open it in Krita 5.2 !</em></p>
<h3 class="anchor anchorWithStickyNavbar_LWe7" id="3-encoding-options">3. Encoding options<a class="hash-link" aria-label="Direct link to 3. Encoding options" title="Direct link to 3. Encoding options" href="https://saklistudio.com/miniblog/krita-jpegxl-tips#3-encoding-options">​</a></h3>
<h4 class="anchor anchorWithStickyNavbar_LWe7" id="lossy-encoding">Lossy encoding<a class="hash-link" aria-label="Direct link to Lossy encoding" title="Direct link to Lossy encoding" href="https://saklistudio.com/miniblog/krita-jpegxl-tips#lossy-encoding">​</a></h4>
<p>JPEG XL can use either <strong>lossy</strong> compression like the old JPEG (but much more improved!), or <strong>lossless</strong> compression like PNG. If you enable this option, it will save as lossy compression and enables some options below.</p>
<h4 class="anchor anchorWithStickyNavbar_LWe7" id="quality">Quality<a class="hash-link" aria-label="Direct link to Quality" title="Direct link to Quality" href="https://saklistudio.com/miniblog/krita-jpegxl-tips#quality">​</a></h4>
<p>This option sets the desired quality for lossy compression. Higher values look better, but lower values have a lower file size. It defaults to 90. Please note that <strong>quality 100 in here doesn't correspond to a lossless</strong> like other apps <em>(in more technical term, it only equals to libjxl distance 0.1)</em>. For a true lossless, you have to disable the Lossy encoding option above!</p>
<h4 class="anchor anchorWithStickyNavbar_LWe7" id="use-modular-mode">Use modular mode<a class="hash-link" aria-label="Direct link to Use modular mode" title="Direct link to Use modular mode" href="https://saklistudio.com/miniblog/krita-jpegxl-tips#use-modular-mode">​</a></h4>
<p>Use the alternative Modular mode for lossy compression. By default, JPEG XL encodes lossy image with VarDCT mode. Sounds pretty technical to you? In short, VarDCT will look like traditional JPEG compression. You can compare the differences when exporting with low quality values!</p>
<h3 class="anchor anchorWithStickyNavbar_LWe7" id="4-tradeoff">4. Tradeoff<a class="hash-link" aria-label="Direct link to 4. Tradeoff" title="Direct link to 4. Tradeoff" href="https://saklistudio.com/miniblog/krita-jpegxl-tips#4-tradeoff">​</a></h3>
<p>Or as known as <strong>Effort</strong> in another apps. The bigger the effort, the better the compression ratio will be but the encoding time will be longer!</p>
<h3 class="anchor anchorWithStickyNavbar_LWe7" id="5-decoding-speed">5. Decoding speed<a class="hash-link" aria-label="Direct link to 5. Decoding speed" title="Direct link to 5. Decoding speed" href="https://saklistudio.com/miniblog/krita-jpegxl-tips#5-decoding-speed">​</a></h3>
<p>Only useful for web delivery optimization to give a faster decoding speed, but generally you should left this option to 0 and barely touch it.</p>
<hr>
<h2 class="anchor anchorWithStickyNavbar_LWe7" id="tips-and-tricks">Tips and Tricks<a class="hash-link" aria-label="Direct link to Tips and Tricks" title="Direct link to Tips and Tricks" href="https://saklistudio.com/miniblog/krita-jpegxl-tips#tips-and-tricks">​</a></h2>
<p>Originally, it should be a hands-off experience when using Krita's JPEG XL export, meaning you shouldn't fiddle much with the options! But on some use cases, it can be beneficial to tweak those options for a better compression or faster encoding time! Let's see some use cases:</p>
<ul>
<li>
<p><strong>Lossy web delivery / uploads</strong>: Check <code>Lossy encoding</code> and set <code>Tradeoff</code> to 7, you can experiment with <code>Use modular mode</code> as well to suit your needs. For the <code>Quality</code> the default 90 is usually good enough for web viewing, unless you need a specific fidelity / filesize target.</p>
</li>
<li>
<p><strong>Pixel Art / small lossless image</strong>: Uncheck <code>Lossy encoding</code> and set <code>Tradeoff</code> to 7. For tiny pixel art images (512px or under), you can go with <code>Tradeoff</code> 9 as well to have a better compression.</p>
</li>
<li>
<p><strong>Medium to large lossless image</strong>: (approx 2k x 2k and up) Uncheck <code>Lossy encoding</code> and set <code>Tradeoff</code> to 1. Indeed this won't be as good as tradeoff 7 for the filesize, but saving time will be much faster.</p>
</li>
</ul>
<p>I need to mention about the trick I often use to reduce color banding, but take note this <strong>only works on 16 bpc canvas</strong> or more!</p>
<div style="max-width:100%"><div aria-owns="rmiz-modal-" data-rmiz=""><div data-rmiz-content="not-found" style="visibility:visible"><picture><source srcset="/miniblog/blog-img/krajxltips/krita-jxl-export-advanced.jxl" type="image/jxl"><img src="https://saklistudio.com/miniblog/blog-img/krajxltips/krita-jxl-export-advanced.png" alt="General Tab"></picture></div></div></div>
<p>Add photon noise! I usually set it around 100-1600 depends on how grainy I'd like it to be and how bad the banding is.</p>
<p>Take a look at some examples of photon noise on very heavy color banding!</p>
<div class="theme-admonition theme-admonition-note admonition_xJq3 alert alert--secondary"><div class="admonitionHeading_Gvgb"><span class="admonitionIcon_Rf37"><svg viewBox="0 0 14 16"><path fill-rule="evenodd" d="M6.3 5.69a.942.942 0 0 1-.28-.7c0-.28.09-.52.28-.7.19-.18.42-.28.7-.28.28 0 .52.09.7.28.18.19.28.42.28.7 0 .28-.09.52-.28.7a1 1 0 0 1-.7.3c-.28 0-.52-.11-.7-.3zM8 7.99c-.02-.25-.11-.48-.31-.69-.2-.19-.42-.3-.69-.31H6c-.27.02-.48.13-.69.31-.2.2-.3.44-.31.69h1v3c.02.27.11.5.31.69.2.2.42.31.69.31h1c.27 0 .48-.11.69-.31.2-.19.3-.42.31-.69H8V7.98v.01zM7 2.3c-3.14 0-5.7 2.54-5.7 5.68 0 3.14 2.56 5.7 5.7 5.7s5.7-2.55 5.7-5.7c0-3.15-2.56-5.69-5.7-5.69v.01zM7 .98c3.86 0 7 3.14 7 7s-3.14 7-7 7-7-3.12-7-7 3.14-7 7-7z"></path></svg></span>note</div><div class="admonitionContent_BuS1"><p><strong>All images below are on JPEG XL only</strong> and will not visible on browsers without JPEG XL support</p></div></div>
<div style="display:flex;flex-flow:wrap;max-width:100%"><img src="https://saklistudio.com/miniblog/blog-img/krajxltips/pnoise0.jxl" alt="ISO 0" style="max-width:100%;height:auto;margin:4px"><img src="https://saklistudio.com/miniblog/blog-img/krajxltips/pnoise200.jxl" alt="ISO 200" style="max-width:100%;height:auto;margin:4px"><img src="https://saklistudio.com/miniblog/blog-img/krajxltips/pnoise800.jxl" alt="ISO 800" style="max-width:100%;height:auto;margin:4px"><img src="https://saklistudio.com/miniblog/blog-img/krajxltips/pnoise3200.jxl" alt="ISO 3200" style="max-width:100%;height:auto;margin:4px"><img src="https://saklistudio.com/miniblog/blog-img/krajxltips/pnoise6400.jxl" alt="ISO 6400" style="max-width:100%;height:auto;margin:4px"><img src="https://saklistudio.com/miniblog/blog-img/krajxltips/pnoise12800.jxl" alt="ISO 12800" style="max-width:100%;height:auto;margin:4px"></div>
<p><em>this is a very bad case of color banding, that's why I need to bump the noise way higher than my usual setting.</em></p>
<hr>
<h2 class="anchor anchorWithStickyNavbar_LWe7" id="how-about-the-image-viewers">How about the image viewers?<a class="hash-link" aria-label="Direct link to How about the image viewers?" title="Direct link to How about the image viewers?" href="https://saklistudio.com/miniblog/krita-jpegxl-tips#how-about-the-image-viewers">​</a></h2>
<p>You can check a list of the <a href="https://github.com/libjxl/libjxl/blob/main/doc/software_support.md" target="_blank" rel="noopener noreferrer">supported softwares</a>. I personally use ImageGlass on windows. If you don't want to install other image viewers and okay to do a little registry edit, <a href="https://github.com/saschanaz/jxl-winthumb" target="_blank" rel="noopener noreferrer">jxl-winthumb</a> is also a good alternative for seamless support in windows.</p>
<h2 class="anchor anchorWithStickyNavbar_LWe7" id="closing-thoughts">Closing thoughts<a class="hash-link" aria-label="Direct link to Closing thoughts" title="Direct link to Closing thoughts" href="https://saklistudio.com/miniblog/krita-jpegxl-tips#closing-thoughts">​</a></h2>
<p>I can say that the export UI is not really polished yet (even as a contributor myself!). But I found out that the library that we use in Krita (libjxl) have quite a lot of options that can be fine tuned, and yet I haven't found out the better way to polish it. For example, I'd like to have the photon noise option to be easily accessible and not hidden in the advanced tab... however, I need more objective opinion to improve it even more! Your testing is very appreciated!</p>]]></content>
        <author>
            <name>Zephyra</name>
            <uri>https://saklistudio.com</uri>
        </author>
        <category label="JPEG XL" term="JPEG XL"/>
        <category label="Krita" term="Krita"/>
        <category label="tutorial" term="tutorial"/>
        <category label="JPEG XL fallback" term="JPEG XL fallback"/>
    </entry>
    <entry>
        <title type="html"><![CDATA[PSO2NGS Blue CAST Fox Showcase]]></title>
        <id>https://saklistudio.com/miniblog/pso2-blue-cast-fox-showcase</id>
        <link href="https://saklistudio.com/miniblog/pso2-blue-cast-fox-showcase"/>
        <updated>2023-10-01T02:00:00.000Z</updated>
        <summary type="html"><![CDATA[A showcase of one of my favorite phasion set on PSO2NGS ^^ Smol blue CAST/robot-ish fox.]]></summary>
        <content type="html"><![CDATA[
<p>A showcase of one of my favorite phasion set on PSO2NGS ^^ Smol blue CAST/robot-ish fox.</p>
<p>Most of the parts are from the base game, but I think it still looks good even on NGS! Totally love the legs part!</p>
<h3 class="anchor anchorWithStickyNavbar_LWe7" id="parts-used">Parts Used<a class="hash-link" aria-label="Direct link to Parts Used" title="Direct link to Parts Used" href="https://saklistudio.com/miniblog/pso2-blue-cast-fox-showcase#parts-used">​</a></h3>
<p>Here's the main parts list:</p>
<ul>
<li><strong>Body</strong>: Sylphos Body</li>
<li><strong>Arms</strong>: Sapphir Arms CV</li>
<li><strong>Legs</strong>: Grizz Legs CV</li>
<li><strong>Head</strong>: Di Gant Head/B <em>(but this is just a placeholder)</em></li>
</ul>
<p>Accessories:</p>
<ul>
<li><strong>Head</strong>: Sylphos mask, Aile Headgear, Krolik Headgear/B, Rithia Hair Ornament</li>
<li><strong>Others</strong>: Crimpiaco Cape, Fluffy Gloves: White</li>
</ul>
<p>Let's start the showcase then! :3</p>
<div style="max-width:100%"><div aria-owns="rmiz-modal-" data-rmiz=""><div data-rmiz-content="not-found" style="visibility:visible"><picture><source srcset="/miniblog/blog-img/bluegrizz/ret-stand.jxl" type="image/jxl"><img src="https://saklistudio.com/miniblog/blog-img/bluegrizz/ret-stand.jpg" alt=""></picture></div></div></div>
<!-- -->
<div style="max-width:100%"><div aria-owns="rmiz-modal-" data-rmiz=""><div data-rmiz-content="not-found" style="visibility:visible"><picture><source srcset="/miniblog/blog-img/bluegrizz/ael-forest-sit.jxl" type="image/jxl"><img src="https://saklistudio.com/miniblog/blog-img/bluegrizz/ael-forest-sit.jpg" alt=""></picture></div></div></div>
<div style="max-width:100%"><div aria-owns="rmiz-modal-" data-rmiz=""><div data-rmiz-content="not-found" style="visibility:visible"><picture><source srcset="/miniblog/blog-img/bluegrizz/ael-forest-sit-wide.jxl" type="image/jxl"><img src="https://saklistudio.com/miniblog/blog-img/bluegrizz/ael-forest-sit-wide.jpg" alt=""></picture></div></div></div>
<div style="max-width:100%"><div aria-owns="rmiz-modal-" data-rmiz=""><div data-rmiz-content="not-found" style="visibility:visible"><picture><source srcset="/miniblog/blog-img/bluegrizz/sti-sitting.jxl" type="image/jxl"><img src="https://saklistudio.com/miniblog/blog-img/bluegrizz/sti-sitting.jpg" alt=""></picture></div></div></div>
<div style="max-width:100%"><div aria-owns="rmiz-modal-" data-rmiz=""><div data-rmiz-content="not-found" style="visibility:visible"><picture><source srcset="/miniblog/blog-img/bluegrizz/sti-sitting-oth.jxl" type="image/jxl"><img src="https://saklistudio.com/miniblog/blog-img/bluegrizz/sti-sitting-oth.jpg" alt=""></picture></div></div></div>
<div style="max-width:100%"><div aria-owns="rmiz-modal-" data-rmiz=""><div data-rmiz-content="not-found" style="visibility:visible"><picture><source srcset="/miniblog/blog-img/bluegrizz/sti-arrow-shot.jxl" type="image/jxl"><img src="https://saklistudio.com/miniblog/blog-img/bluegrizz/sti-arrow-shot.jpg" alt=""></picture></div></div></div>
<div style="max-width:100%"><div aria-owns="rmiz-modal-" data-rmiz=""><div data-rmiz-content="not-found" style="visibility:visible"><picture><source srcset="/miniblog/blog-img/bluegrizz/sti-arrow-released.jxl" type="image/jxl"><img src="https://saklistudio.com/miniblog/blog-img/bluegrizz/sti-arrow-released.jpg" alt=""></picture></div></div></div>
<div style="max-width:100%"><div aria-owns="rmiz-modal-" data-rmiz=""><div data-rmiz-content="not-found" style="visibility:visible"><picture><source srcset="/miniblog/blog-img/bluegrizz/home-sleeping.jxl" type="image/jxl"><img src="https://saklistudio.com/miniblog/blog-img/bluegrizz/home-sleeping.jpg" alt=""></picture></div></div></div>
<div style="max-width:100%"><div aria-owns="rmiz-modal-" data-rmiz=""><div data-rmiz-content="not-found" style="visibility:visible"><picture><source srcset="/miniblog/blog-img/bluegrizz/home-bath.jxl" type="image/jxl"><img src="https://saklistudio.com/miniblog/blog-img/bluegrizz/home-bath.jpg" alt=""></picture></div></div></div>
<h3 class="anchor anchorWithStickyNavbar_LWe7" id="bonus-pink-claw-boots-on-my-personal-space">Bonus: Pink claw boots on my Personal Space!<a class="hash-link" aria-label="Direct link to Bonus: Pink claw boots on my Personal Space!" title="Direct link to Bonus: Pink claw boots on my Personal Space!" href="https://saklistudio.com/miniblog/pso2-blue-cast-fox-showcase#bonus-pink-claw-boots-on-my-personal-space">​</a></h3>
<div style="max-width:100%"><div aria-owns="rmiz-modal-" data-rmiz=""><div data-rmiz-content="not-found" style="visibility:visible"><picture><source srcset="/miniblog/blog-img/bluegrizz/home-pink-claws.jxl" type="image/jxl"><img src="https://saklistudio.com/miniblog/blog-img/bluegrizz/home-pink-claws.jpg" alt=""></picture></div></div></div>
<hr>
<div class="theme-admonition theme-admonition-note admonition_xJq3 alert alert--secondary"><div class="admonitionHeading_Gvgb"><span class="admonitionIcon_Rf37"><svg viewBox="0 0 14 16"><path fill-rule="evenodd" d="M6.3 5.69a.942.942 0 0 1-.28-.7c0-.28.09-.52.28-.7.19-.18.42-.28.7-.28.28 0 .52.09.7.28.18.19.28.42.28.7 0 .28-.09.52-.28.7a1 1 0 0 1-.7.3c-.28 0-.52-.11-.7-.3zM8 7.99c-.02-.25-.11-.48-.31-.69-.2-.19-.42-.3-.69-.31H6c-.27.02-.48.13-.69.31-.2.2-.3.44-.31.69h1v3c.02.27.11.5.31.69.2.2.42.31.69.31h1c.27 0 .48-.11.69-.31.2-.19.3-.42.31-.69H8V7.98v.01zM7 2.3c-3.14 0-5.7 2.54-5.7 5.68 0 3.14 2.56 5.7 5.7 5.7s5.7-2.55 5.7-5.7c0-3.15-2.56-5.69-5.7-5.69v.01zM7 .98c3.86 0 7 3.14 7 7s-3.14 7-7 7-7-3.12-7-7 3.14-7 7-7z"></path></svg></span>note</div><div class="admonitionContent_BuS1"><p>The images are at full 2.5k res (2560x1440) and served both in JPEG XL and JPG as a falback on unsupported browsers. JXL encoding parameters are q=90 / d=1.0 and JPG encoding parameters are approximately matched <strong>to the file size</strong> of JXL counterpart, which is around q=70 on Krita 5.2</p></div></div>]]></content>
        <author>
            <name>Kisi</name>
            <uri>https://saklistudio.com</uri>
        </author>
        <category label="gaming" term="gaming"/>
        <category label="PSO2NGS" term="PSO2NGS"/>
        <category label="JPEG XL fallback" term="JPEG XL fallback"/>
    </entry>
    <entry>
        <title type="html"><![CDATA[Hidden Art of Unclamping jxlart Artworks]]></title>
        <id>https://saklistudio.com/miniblog/jxl-art-unclamp</id>
        <link href="https://saklistudio.com/miniblog/jxl-art-unclamp"/>
        <updated>2023-09-29T06:51:00.000Z</updated>
        <summary type="html"><![CDATA[Background Story]]></summary>
        <content type="html"><![CDATA[<h2 class="anchor anchorWithStickyNavbar_LWe7" id="background-story">Background Story<a class="hash-link" aria-label="Direct link to Background Story" title="Direct link to Background Story" href="https://saklistudio.com/miniblog/jxl-art-unclamp#background-story">​</a></h2>
<p>On my post about <a href="https://saklistudio.com/jxlcoloranalysis/" target="_blank" rel="noopener noreferrer">JPEG XL color analysis</a> I mentioned that JXL stores lossy XYB in absolute, float values that can be requested during decoding process by calling pixel format <code>data_type</code> as <code>JXL_TYPE_FLOAT</code>, where out-of-gamut colors are represented with negative values.</p>
<p>I was recently encouraged by <strong>Amyspark</strong> from <strong>Krita</strong> 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</p>
<!-- -->
<p>And here goes the project result. I added a support for 3D plotting in xyY axes as well for the cherry on top. The 3D is not quite a performant one though, can only be plotted with very small points due to very expensive allocation of one-series-per-pixel needed for the <code>Q3DScatter</code> chart, because the color can't be set per data point, only per series. Thus that's why I also include a monochromatic series to plot with higher density points, although that also a bit sluggish even on my system with RTX 2080 GPU. And for the 2D plot, at first I want to utilize <code>QChartView</code> as well, but hitting the same issue like 3D one, only one color per series and gets exponentially more expensive as the point density rising. Finally I escorted to a custom <code>QWidget</code>, inspired from Krita's CIE Tongue Widget that could be seen when opening an advanced color space selector, adding more features here and there for the ease of chart manipulation. It still wasn't optimized enough and still runs on single core, but it already performs way faster than the python-based one.</p>
<p>Then there was an image file handling issues. The basic <code>QImage</code> itself is already enough to handle most of the common formats like <code>JPEG</code> and <code>PNG</code>. But c'mon, this project was (primarily) meant for <code>JPEG XL</code> as well. And coding wise, integrating libjxl decoding was pretty trivial. But compiling wise, was a bit of a brickwall. I don't know why building <code>libjxl</code> with Qt's MingW kits kept triggering a dll missing entry point or something, even with static C/CXX flags set on libjxl. And even if it does eventually built, there were random crashes when loading specific images. And then I build it separately with LLVM ucrt kits like the one used in Krita build, thus everything works smoothly. Pretty unsure how safe it is to mix the main binary that built with Qt's Mingw kit with deps binary that built with LLVM.. <em>(but since both use <code>gcc</code> and <code>g++</code>, it should be fine I guess?)</em>. Anyway, I got it working and set the decode to always ask for unclamped <code>float32</code>.</p>
<p>So here goes the results of some #jxlart plotting, some results were quite stunning with unclamped values! Source JXL art are provided from Jon's official #jxlart page and libjxl discord server.</p>
<hr>
<p>Credit to <strong>Jon Sneyers</strong> for the #jxlart sources!</p>
<h2 class="anchor anchorWithStickyNavbar_LWe7" id="from-jons-official-jxlart-page"><a href="https://jpegxl.info/art/2021-04_jon.html" target="_blank" rel="noopener noreferrer">From Jon's Official #jxlart Page</a><a class="hash-link" aria-label="Direct link to from-jons-official-jxlart-page" title="Direct link to from-jons-official-jxlart-page" href="https://saklistudio.com/miniblog/jxl-art-unclamp#from-jons-official-jxlart-page">​</a></h2>
<h3 class="anchor anchorWithStickyNavbar_LWe7" id="jxl-logo">JXL Logo<a class="hash-link" aria-label="Direct link to JXL Logo" title="Direct link to JXL Logo" href="https://saklistudio.com/miniblog/jxl-art-unclamp#jxl-logo">​</a></h3>
<div style="max-width:100%"><div aria-owns="rmiz-modal-" data-rmiz=""><div data-rmiz-content="not-found" style="visibility:visible"><picture><source srcset="/miniblog/blog-img/jxlartplot/JXL-Logo-plot.jxl" type="image/jxl"><img src="https://saklistudio.com/miniblog/blog-img/jxlartplot/JXL-Logo-plot.png" alt=""></picture></div></div></div>
<h3 class="anchor anchorWithStickyNavbar_LWe7" id="the-smoke-machine">The Smoke Machine<a class="hash-link" aria-label="Direct link to The Smoke Machine" title="Direct link to The Smoke Machine" href="https://saklistudio.com/miniblog/jxl-art-unclamp#the-smoke-machine">​</a></h3>
<div style="max-width:100%"><div aria-owns="rmiz-modal-" data-rmiz=""><div data-rmiz-content="not-found" style="visibility:visible"><picture><source srcset="/miniblog/blog-img/jxlartplot/The-Smoke-Machine-plot.jxl" type="image/jxl"><img src="https://saklistudio.com/miniblog/blog-img/jxlartplot/The-Smoke-Machine-plot.png" alt=""></picture></div></div></div>
<h3 class="anchor anchorWithStickyNavbar_LWe7" id="minor-misalignment">Minor Misalignment<a class="hash-link" aria-label="Direct link to Minor Misalignment" title="Direct link to Minor Misalignment" href="https://saklistudio.com/miniblog/jxl-art-unclamp#minor-misalignment">​</a></h3>
<div style="max-width:100%"><div aria-owns="rmiz-modal-" data-rmiz=""><div data-rmiz-content="not-found" style="visibility:visible"><picture><source srcset="/miniblog/blog-img/jxlartplot/Minor-Misalignment-plot.jxl" type="image/jxl"><img src="https://saklistudio.com/miniblog/blog-img/jxlartplot/Minor-Misalignment-plot.png" alt=""></picture></div></div></div>
<h3 class="anchor anchorWithStickyNavbar_LWe7" id="inside-the-flying-spaghetti-monster">Inside The Flying Spaghetti Monster<a class="hash-link" aria-label="Direct link to Inside The Flying Spaghetti Monster" title="Direct link to Inside The Flying Spaghetti Monster" href="https://saklistudio.com/miniblog/jxl-art-unclamp#inside-the-flying-spaghetti-monster">​</a></h3>
<div style="max-width:100%"><div aria-owns="rmiz-modal-" data-rmiz=""><div data-rmiz-content="not-found" style="visibility:visible"><picture><source srcset="/miniblog/blog-img/jxlartplot/Inside-The-FSM-plot.jxl" type="image/jxl"><img src="https://saklistudio.com/miniblog/blog-img/jxlartplot/Inside-The-FSM-plot.png" alt=""></picture></div></div></div>
<h3 class="anchor anchorWithStickyNavbar_LWe7" id="alien-message">Alien Message<a class="hash-link" aria-label="Direct link to Alien Message" title="Direct link to Alien Message" href="https://saklistudio.com/miniblog/jxl-art-unclamp#alien-message">​</a></h3>
<div style="max-width:100%"><div aria-owns="rmiz-modal-" data-rmiz=""><div data-rmiz-content="not-found" style="visibility:visible"><picture><source srcset="/miniblog/blog-img/jxlartplot/Alien-Message-plot.jxl" type="image/jxl"><img src="https://saklistudio.com/miniblog/blog-img/jxlartplot/Alien-Message-plot.png" alt=""></picture></div></div></div>
<h3 class="anchor anchorWithStickyNavbar_LWe7" id="alien-bushfires">Alien Bushfires<a class="hash-link" aria-label="Direct link to Alien Bushfires" title="Direct link to Alien Bushfires" href="https://saklistudio.com/miniblog/jxl-art-unclamp#alien-bushfires">​</a></h3>
<div style="max-width:100%"><div aria-owns="rmiz-modal-" data-rmiz=""><div data-rmiz-content="not-found" style="visibility:visible"><picture><source srcset="/miniblog/blog-img/jxlartplot/Alien-Bushfires-plot.jxl" type="image/jxl"><img src="https://saklistudio.com/miniblog/blog-img/jxlartplot/Alien-Bushfires-plot.png" alt=""></picture></div></div></div>
<h2 class="anchor anchorWithStickyNavbar_LWe7" id="from-discord-and-twitter">From Discord and Twitter<a class="hash-link" aria-label="Direct link to From Discord and Twitter" title="Direct link to From Discord and Twitter" href="https://saklistudio.com/miniblog/jxl-art-unclamp#from-discord-and-twitter">​</a></h2>
<h3 class="anchor anchorWithStickyNavbar_LWe7" id="colored-aurora"><a href="https://twitter.com/jonsneyers/status/1563283769334718464?s=20" target="_blank" rel="noopener noreferrer">Colored Aurora</a><a class="hash-link" aria-label="Direct link to colored-aurora" title="Direct link to colored-aurora" href="https://saklistudio.com/miniblog/jxl-art-unclamp#colored-aurora">​</a></h3>
<div style="max-width:100%"><div aria-owns="rmiz-modal-" data-rmiz=""><div data-rmiz-content="not-found" style="visibility:visible"><picture><source srcset="/miniblog/blog-img/jxlartplot/Colored-Aurora-plot.jxl" type="image/jxl"><img src="https://saklistudio.com/miniblog/blog-img/jxlartplot/Colored-Aurora-plot.png" alt=""></picture></div></div></div>
<h3 class="anchor anchorWithStickyNavbar_LWe7" id="sierpinski-foam-8k-with-alpha"><a href="https://jxl-art.surma.technology/?zcode=TY4xC8IwFIT39ytuL4FqW9FFUAedIlglczDPJlBrrM%2FFX28iIm733QfHrYM4juJR0WFzREkmuESLWUk7Dp0XNHVJp%2Fiw19gz5rQfAw9iJdwGTKi9P5lfTKs%2BeksULjhjiYaAFE2hlTaJq8SAgoaqP%2FFffqvst6N1eR3TX2VQZK%2FQsqR3bw%3D%3D" target="_blank" rel="noopener noreferrer">Sierpinski Foam (8K, with alpha)</a><a class="hash-link" aria-label="Direct link to sierpinski-foam-8k-with-alpha" title="Direct link to sierpinski-foam-8k-with-alpha" href="https://saklistudio.com/miniblog/jxl-art-unclamp#sierpinski-foam-8k-with-alpha">​</a></h3>
<div style="max-width:100%"><div aria-owns="rmiz-modal-" data-rmiz=""><div data-rmiz-content="not-found" style="visibility:visible"><picture><source srcset="/miniblog/blog-img/jxlartplot/Sierpinski-foam-8k-plot.jxl" type="image/jxl"><img src="https://saklistudio.com/miniblog/blog-img/jxlartplot/Sierpinski-foam-8k-plot.png" alt=""></picture></div></div></div>
<p><em>Feel free to test it more! I posted the source and prebuild Win64 binaries back in the <a href="https://github.com/kampidh/Color-Gamut-Plotter-QtVer" target="_blank" rel="noopener noreferrer">project's github page</a>.</em></p>]]></content>
        <author>
            <name>Kampidh</name>
            <uri>https://saklistudio.com</uri>
        </author>
        <category label="JPEG XL" term="JPEG XL"/>
        <category label="coding" term="coding"/>
        <category label="art" term="art"/>
    </entry>
    <entry>
        <title type="html"><![CDATA[Fiddling With Docusaurus]]></title>
        <id>https://saklistudio.com/miniblog/fiddling-with-docusaurus</id>
        <link href="https://saklistudio.com/miniblog/fiddling-with-docusaurus"/>
        <updated>2023-09-28T13:22:00.000Z</updated>
        <summary type="html"><![CDATA[{/* <JxlLoader]]></summary>
        <content type="html"><![CDATA[
<p><em>depends on how you view it, but I don't feel like reinventing a wheel just to make a static blog site. haha</em><br>
On the positive side, I can throw <code>JPEG-XL</code> images here too and get it rendered on supported browsers, <em><strong>yay!</strong></em></p>
<div class="language-md codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#bfc7d5;--prism-background-color:#292d3e"><div class="codeBlockContent_biex"><pre tabindex="0" class="prism-code language-md codeBlock_bY9V thin-scrollbar" style="color:#bfc7d5;background-color:#292d3e"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#bfc7d5"><span class="token url operator" style="color:rgb(137, 221, 255)">!</span><span class="token url" style="color:rgb(221, 221, 221)">[</span><span class="token url content" style="color:rgb(221, 221, 221)">Spectral Zephyr</span><span class="token url" style="color:rgb(221, 221, 221)">](</span><span class="token url" style="color:rgb(221, 221, 221)">./zeph-spectral.jxl</span><span class="token url" style="color:rgb(221, 221, 221)">)</span><br></span></code></pre><div class="buttonGroup__atx"><button type="button" aria-label="Copy code to clipboard" title="Copy" class="clean-btn"><span class="copyButtonIcons_eSgA" aria-hidden="true"><svg viewBox="0 0 24 24" class="copyButtonIcon_y97N"><path fill="currentColor" d="M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z"></path></svg><svg viewBox="0 0 24 24" class="copyButtonSuccessIcon_LjdS"><path fill="currentColor" d="M21,7L9,19L3.5,13.5L4.91,12.09L9,16.17L19.59,5.59L21,7Z"></path></svg></span></button></div></div></div>
<div aria-owns="rmiz-modal-" data-rmiz=""><div data-rmiz-content="not-found" style="visibility:visible"><p><img loading="lazy" alt="Spectral Zephyr" src="https://saklistudio.com/miniblog/assets/images/zeph-spectral-d0dbcb8e062210d58d84ada25f64b1c3.jxl" class="img_CujE"></p></div></div>
<div class="theme-admonition theme-admonition-warning admonition_xJq3 alert alert--warning"><div class="admonitionHeading_Gvgb"><span class="admonitionIcon_Rf37"><svg viewBox="0 0 16 16"><path fill-rule="evenodd" d="M8.893 1.5c-.183-.31-.52-.5-.887-.5s-.703.19-.886.5L.138 13.499a.98.98 0 0 0 0 1.001c.193.31.53.501.886.501h13.964c.367 0 .704-.19.877-.5a1.03 1.03 0 0 0 .01-1.002L8.893 1.5zm.133 11.497H6.987v-2.003h2.039v2.003zm0-3.004H6.987V5.987h2.039v4.006z"></path></svg></span>zooming</div><div class="admonitionContent_BuS1"><p>May break on JXL-unsupported browsers if you try to zoom a broken/unrendered image and may freeze the page! For example I use <code>react-medium-image-zoom</code> plugin for image zooming in this page.</p></div></div>
<p>Although Docusaurus always complains a lot during compile time:</p>
<div class="codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#bfc7d5;--prism-background-color:#292d3e"><div class="codeBlockContent_biex"><pre tabindex="0" class="prism-code language-text codeBlock_bY9V thin-scrollbar" style="color:#bfc7d5;background-color:#292d3e"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#bfc7d5"><span class="token plain">[WARNING] The image at "{path_to_image.jxl}" can't be read correctly. Please ensure it's a valid image.</span><br></span><span class="token-line" style="color:#bfc7d5"><span class="token plain">unsupported file type: undefined (file: {path_to_image.jxl})</span><br></span></code></pre><div class="buttonGroup__atx"><button type="button" aria-label="Copy code to clipboard" title="Copy" class="clean-btn"><span class="copyButtonIcons_eSgA" aria-hidden="true"><svg viewBox="0 0 24 24" class="copyButtonIcon_y97N"><path fill="currentColor" d="M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z"></path></svg><svg viewBox="0 0 24 24" class="copyButtonSuccessIcon_LjdS"><path fill="currentColor" d="M21,7L9,19L3.5,13.5L4.91,12.09L9,16.17L19.59,5.59L21,7Z"></path></svg></span></button></div></div></div>
<p>And nope, using JSX didn't work either...</p>
<div class="codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#bfc7d5;--prism-background-color:#292d3e"><div class="codeBlockContent_biex"><pre tabindex="0" class="prism-code language-text codeBlock_bY9V thin-scrollbar" style="color:#bfc7d5;background-color:#292d3e"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#bfc7d5"><span class="token plain">ERROR in {path_to_image.jxl} 1:0</span><br></span><span class="token-line" style="color:#bfc7d5"><span class="token plain">Module parse failed: Unexpected character '' (1:0)</span><br></span><span class="token-line" style="color:#bfc7d5"><span class="token plain">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</span><br></span><span class="token-line" style="color:#bfc7d5"><span class="token plain">(Source code omitted for this binary file)</span><br></span></code></pre><div class="buttonGroup__atx"><button type="button" aria-label="Copy code to clipboard" title="Copy" class="clean-btn"><span class="copyButtonIcons_eSgA" aria-hidden="true"><svg viewBox="0 0 24 24" class="copyButtonIcon_y97N"><path fill="currentColor" d="M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z"></path></svg><svg viewBox="0 0 24 24" class="copyButtonSuccessIcon_LjdS"><path fill="currentColor" d="M21,7L9,19L3.5,13.5L4.91,12.09L9,16.17L19.59,5.59L21,7Z"></path></svg></span></button></div></div></div>
<p>So yeah, sadly <code>&lt;picture&gt;</code> tag didn't work with JXL here either!</p>
<hr>
<h2 class="anchor anchorWithStickyNavbar_LWe7" id="edit-found-some-workaround-yay">EDIT: Found some workaround yay!<a class="hash-link" aria-label="Direct link to EDIT: Found some workaround yay!" title="Direct link to EDIT: Found some workaround yay!" href="https://saklistudio.com/miniblog/fiddling-with-docusaurus#edit-found-some-workaround-yay">​</a></h2>
<ul>
<li>
<p>The first one is to insert <code>file-loader!</code> before the URL, for example image below:</p>
<div class="language-jsx codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#bfc7d5;--prism-background-color:#292d3e"><div class="codeBlockContent_biex"><pre tabindex="0" class="prism-code language-jsx codeBlock_bY9V thin-scrollbar" style="color:#bfc7d5;background-color:#292d3e"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#bfc7d5"><span class="token tag punctuation" style="color:rgb(199, 146, 234)">&lt;</span><span class="token tag" style="color:rgb(255, 85, 114)">picture</span><span class="token tag punctuation" style="color:rgb(199, 146, 234)">&gt;</span><span class="token plain-text"></span><br></span><span class="token-line" style="color:#bfc7d5"><span class="token plain-text">    </span><span class="token tag punctuation" style="color:rgb(199, 146, 234)">&lt;</span><span class="token tag" style="color:rgb(255, 85, 114)">source</span><span class="token tag" style="color:rgb(255, 85, 114)"> </span><span class="token tag attr-name" style="color:rgb(255, 203, 107)">srcSet</span><span class="token tag script language-javascript script-punctuation punctuation" style="color:rgb(199, 146, 234)">=</span><span class="token tag script language-javascript punctuation" style="color:rgb(199, 146, 234)">{</span><span class="token tag script language-javascript function" style="color:rgb(130, 170, 255)">require</span><span class="token tag script language-javascript punctuation" style="color:rgb(199, 146, 234)">(</span><span class="token tag script language-javascript string" style="color:rgb(195, 232, 141)">"file-loader!./dv-nebia-nevia-sub.jxl"</span><span class="token tag script language-javascript punctuation" style="color:rgb(199, 146, 234)">)</span><span class="token tag script language-javascript punctuation" style="color:rgb(199, 146, 234)">.</span><span class="token tag script language-javascript keyword module" style="color:rgb(255, 85, 114);font-style:italic">default</span><span class="token tag script language-javascript punctuation" style="color:rgb(199, 146, 234)">}</span><span class="token tag" style="color:rgb(255, 85, 114)"> </span><span class="token tag attr-name" style="color:rgb(255, 203, 107)">type</span><span class="token tag attr-value punctuation attr-equals" style="color:rgb(199, 146, 234)">=</span><span class="token tag attr-value punctuation" style="color:rgb(199, 146, 234)">"</span><span class="token tag attr-value" style="color:rgb(255, 85, 114)">image/jxl</span><span class="token tag attr-value punctuation" style="color:rgb(199, 146, 234)">"</span><span class="token tag punctuation" style="color:rgb(199, 146, 234)">/&gt;</span><span class="token plain-text"></span><br></span><span class="token-line" style="color:#bfc7d5"><span class="token plain-text">    </span><span class="token tag punctuation" style="color:rgb(199, 146, 234)">&lt;</span><span class="token tag" style="color:rgb(255, 85, 114)">img</span><span class="token tag" style="color:rgb(255, 85, 114)"> </span><span class="token tag attr-name" style="color:rgb(255, 203, 107)">src</span><span class="token tag script language-javascript script-punctuation punctuation" style="color:rgb(199, 146, 234)">=</span><span class="token tag script language-javascript punctuation" style="color:rgb(199, 146, 234)">{</span><span class="token tag script language-javascript function" style="color:rgb(130, 170, 255)">require</span><span class="token tag script language-javascript punctuation" style="color:rgb(199, 146, 234)">(</span><span class="token tag script language-javascript string" style="color:rgb(195, 232, 141)">"./dv-nebia-nevia-sub.jpg"</span><span class="token tag script language-javascript punctuation" style="color:rgb(199, 146, 234)">)</span><span class="token tag script language-javascript punctuation" style="color:rgb(199, 146, 234)">.</span><span class="token tag script language-javascript keyword module" style="color:rgb(255, 85, 114);font-style:italic">default</span><span class="token tag script language-javascript punctuation" style="color:rgb(199, 146, 234)">}</span><span class="token tag" style="color:rgb(255, 85, 114)"> </span><span class="token tag attr-name" style="color:rgb(255, 203, 107)">width</span><span class="token tag attr-value punctuation attr-equals" style="color:rgb(199, 146, 234)">=</span><span class="token tag attr-value punctuation" style="color:rgb(199, 146, 234)">"</span><span class="token tag attr-value" style="color:rgb(255, 85, 114)">100%</span><span class="token tag attr-value punctuation" style="color:rgb(199, 146, 234)">"</span><span class="token tag" style="color:rgb(255, 85, 114)"> </span><span class="token tag punctuation" style="color:rgb(199, 146, 234)">/&gt;</span><span class="token plain-text"></span><br></span><span class="token-line" style="color:#bfc7d5"><span class="token plain-text"></span><span class="token tag punctuation" style="color:rgb(199, 146, 234)">&lt;/</span><span class="token tag" style="color:rgb(255, 85, 114)">picture</span><span class="token tag punctuation" style="color:rgb(199, 146, 234)">&gt;</span><br></span></code></pre><div class="buttonGroup__atx"><button type="button" aria-label="Copy code to clipboard" title="Copy" class="clean-btn"><span class="copyButtonIcons_eSgA" aria-hidden="true"><svg viewBox="0 0 24 24" class="copyButtonIcon_y97N"><path fill="currentColor" d="M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z"></path></svg><svg viewBox="0 0 24 24" class="copyButtonSuccessIcon_LjdS"><path fill="currentColor" d="M21,7L9,19L3.5,13.5L4.91,12.09L9,16.17L19.59,5.59L21,7Z"></path></svg></span></button></div></div></div>
<p>However, this method requires a manual insertion for each <code>&lt;picture&gt;</code> tag and will strip any filenames <em>(which is sad!)</em>. If the image is still broken, use <code>!!file-loader!</code> instead. Or maybe Docusaurus already fixed the module on the next method!</p>
</li>
<li>
<p>The second method requires to fiddle with Docusaurus' <code>webpackUtils</code> source which will use the internal parsing and keeping the filename intact:</p>
<p>On <code>node_modules</code>, find <code>webpackUtils.js</code> and/or <code>webpackUtils.ts</code>. In my case it's on <code>node_modules/@docusaurus/utils/lib/</code>. Open the file and find <code>getFileLoaderUtils()</code> function, on <code>const rules</code> variable find <code>image</code> field and add <code>jxl</code> to the list:</p>
<div class="language-js codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#bfc7d5;--prism-background-color:#292d3e"><div class="codeBlockContent_biex"><pre tabindex="0" class="prism-code language-js codeBlock_bY9V thin-scrollbar" style="color:#bfc7d5;background-color:#292d3e"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#bfc7d5"><span class="token function-variable function" style="color:rgb(130, 170, 255)">images</span><span class="token operator" style="color:rgb(137, 221, 255)">:</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(199, 146, 234)">(</span><span class="token punctuation" style="color:rgb(199, 146, 234)">)</span><span class="token plain"> </span><span class="token arrow operator" style="color:rgb(137, 221, 255)">=&gt;</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(199, 146, 234)">(</span><span class="token punctuation" style="color:rgb(199, 146, 234)">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#bfc7d5"><span class="token plain">    </span><span class="token literal-property property">use</span><span class="token operator" style="color:rgb(137, 221, 255)">:</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(199, 146, 234)">[</span><span class="token plain">loaders</span><span class="token punctuation" style="color:rgb(199, 146, 234)">.</span><span class="token method function property-access" style="color:rgb(130, 170, 255)">url</span><span class="token punctuation" style="color:rgb(199, 146, 234)">(</span><span class="token punctuation" style="color:rgb(199, 146, 234)">{</span><span class="token plain"> </span><span class="token literal-property property">folder</span><span class="token operator" style="color:rgb(137, 221, 255)">:</span><span class="token plain"> </span><span class="token string" style="color:rgb(195, 232, 141)">'images'</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(199, 146, 234)">}</span><span class="token punctuation" style="color:rgb(199, 146, 234)">)</span><span class="token punctuation" style="color:rgb(199, 146, 234)">]</span><span class="token punctuation" style="color:rgb(199, 146, 234)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#bfc7d5"><span class="token plain">    </span><span class="token literal-property property">test</span><span class="token operator" style="color:rgb(137, 221, 255)">:</span><span class="token plain"> </span><span class="token regex regex-delimiter">/</span><span class="token regex regex-source language-regex special-escape escape">\.</span><span class="token regex regex-source language-regex group punctuation" style="color:rgb(199, 146, 234)">(?:</span><span class="token regex regex-source language-regex">ico</span><span class="token regex regex-source language-regex alternation keyword" style="font-style:italic">|</span><span class="token regex regex-source language-regex">jpe</span><span class="token regex regex-source language-regex quantifier number" style="color:rgb(247, 140, 108)">?</span><span class="token regex regex-source language-regex">g</span><span class="token regex regex-source language-regex alternation keyword" style="font-style:italic">|</span><span class="token regex regex-source language-regex">png</span><span class="token regex regex-source language-regex alternation keyword" style="font-style:italic">|</span><span class="token regex regex-source language-regex">gif</span><span class="token regex regex-source language-regex alternation keyword" style="font-style:italic">|</span><span class="token regex regex-source language-regex">webp</span><span class="token regex regex-source language-regex alternation keyword" style="font-style:italic">|</span><span class="token regex regex-source language-regex">avif</span><span class="token regex regex-source language-regex alternation keyword" style="font-style:italic">|</span><span class="token regex regex-source language-regex">jxl</span><span class="token regex regex-source language-regex group punctuation" style="color:rgb(199, 146, 234)">)</span><span class="token regex regex-source language-regex group punctuation" style="color:rgb(199, 146, 234)">(?:</span><span class="token regex regex-source language-regex special-escape escape">\?</span><span class="token regex regex-source language-regex char-set class-name" style="color:rgb(255, 203, 107)">.</span><span class="token regex regex-source language-regex quantifier number" style="color:rgb(247, 140, 108)">*</span><span class="token regex regex-source language-regex group punctuation" style="color:rgb(199, 146, 234)">)</span><span class="token regex regex-source language-regex quantifier number" style="color:rgb(247, 140, 108)">?</span><span class="token regex regex-source language-regex anchor function" style="color:rgb(130, 170, 255)">$</span><span class="token regex regex-delimiter">/</span><span class="token regex regex-flags">i</span><span class="token punctuation" style="color:rgb(199, 146, 234)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#bfc7d5"><span class="token plain"></span><span class="token punctuation" style="color:rgb(199, 146, 234)">}</span><span class="token punctuation" style="color:rgb(199, 146, 234)">)</span><span class="token punctuation" style="color:rgb(199, 146, 234)">,</span><br></span></code></pre><div class="buttonGroup__atx"><button type="button" aria-label="Copy code to clipboard" title="Copy" class="clean-btn"><span class="copyButtonIcons_eSgA" aria-hidden="true"><svg viewBox="0 0 24 24" class="copyButtonIcon_y97N"><path fill="currentColor" d="M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z"></path></svg><svg viewBox="0 0 24 24" class="copyButtonSuccessIcon_LjdS"><path fill="currentColor" d="M21,7L9,19L3.5,13.5L4.91,12.09L9,16.17L19.59,5.59L21,7Z"></path></svg></span></button></div></div></div>
<p>This way we don't need to add <code>file-loader!</code> and just add an URL like usual!</p>
<div class="language-jsx codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#bfc7d5;--prism-background-color:#292d3e"><div class="codeBlockContent_biex"><pre tabindex="0" class="prism-code language-jsx codeBlock_bY9V thin-scrollbar" style="color:#bfc7d5;background-color:#292d3e"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#bfc7d5"><span class="token tag punctuation" style="color:rgb(199, 146, 234)">&lt;</span><span class="token tag" style="color:rgb(255, 85, 114)">picture</span><span class="token tag punctuation" style="color:rgb(199, 146, 234)">&gt;</span><span class="token plain-text"></span><br></span><span class="token-line" style="color:#bfc7d5"><span class="token plain-text">    </span><span class="token tag punctuation" style="color:rgb(199, 146, 234)">&lt;</span><span class="token tag" style="color:rgb(255, 85, 114)">source</span><span class="token tag" style="color:rgb(255, 85, 114)"> </span><span class="token tag attr-name" style="color:rgb(255, 203, 107)">srcSet</span><span class="token tag script language-javascript script-punctuation punctuation" style="color:rgb(199, 146, 234)">=</span><span class="token tag script language-javascript punctuation" style="color:rgb(199, 146, 234)">{</span><span class="token tag script language-javascript function" style="color:rgb(130, 170, 255)">require</span><span class="token tag script language-javascript punctuation" style="color:rgb(199, 146, 234)">(</span><span class="token tag script language-javascript string" style="color:rgb(195, 232, 141)">"./dv-nebia-nevia-sub.jxl"</span><span class="token tag script language-javascript punctuation" style="color:rgb(199, 146, 234)">)</span><span class="token tag script language-javascript punctuation" style="color:rgb(199, 146, 234)">.</span><span class="token tag script language-javascript keyword module" style="color:rgb(255, 85, 114);font-style:italic">default</span><span class="token tag script language-javascript punctuation" style="color:rgb(199, 146, 234)">}</span><span class="token tag" style="color:rgb(255, 85, 114)"> </span><span class="token tag attr-name" style="color:rgb(255, 203, 107)">type</span><span class="token tag attr-value punctuation attr-equals" style="color:rgb(199, 146, 234)">=</span><span class="token tag attr-value punctuation" style="color:rgb(199, 146, 234)">"</span><span class="token tag attr-value" style="color:rgb(255, 85, 114)">image/jxl</span><span class="token tag attr-value punctuation" style="color:rgb(199, 146, 234)">"</span><span class="token tag punctuation" style="color:rgb(199, 146, 234)">/&gt;</span><span class="token plain-text"></span><br></span><span class="token-line" style="color:#bfc7d5"><span class="token plain-text">    </span><span class="token tag punctuation" style="color:rgb(199, 146, 234)">&lt;</span><span class="token tag" style="color:rgb(255, 85, 114)">img</span><span class="token tag" style="color:rgb(255, 85, 114)"> </span><span class="token tag attr-name" style="color:rgb(255, 203, 107)">src</span><span class="token tag script language-javascript script-punctuation punctuation" style="color:rgb(199, 146, 234)">=</span><span class="token tag script language-javascript punctuation" style="color:rgb(199, 146, 234)">{</span><span class="token tag script language-javascript function" style="color:rgb(130, 170, 255)">require</span><span class="token tag script language-javascript punctuation" style="color:rgb(199, 146, 234)">(</span><span class="token tag script language-javascript string" style="color:rgb(195, 232, 141)">"./dv-nebia-nevia-sub.jpg"</span><span class="token tag script language-javascript punctuation" style="color:rgb(199, 146, 234)">)</span><span class="token tag script language-javascript punctuation" style="color:rgb(199, 146, 234)">.</span><span class="token tag script language-javascript keyword module" style="color:rgb(255, 85, 114);font-style:italic">default</span><span class="token tag script language-javascript punctuation" style="color:rgb(199, 146, 234)">}</span><span class="token tag" style="color:rgb(255, 85, 114)"> </span><span class="token tag attr-name" style="color:rgb(255, 203, 107)">width</span><span class="token tag attr-value punctuation attr-equals" style="color:rgb(199, 146, 234)">=</span><span class="token tag attr-value punctuation" style="color:rgb(199, 146, 234)">"</span><span class="token tag attr-value" style="color:rgb(255, 85, 114)">100%</span><span class="token tag attr-value punctuation" style="color:rgb(199, 146, 234)">"</span><span class="token tag" style="color:rgb(255, 85, 114)"> </span><span class="token tag punctuation" style="color:rgb(199, 146, 234)">/&gt;</span><span class="token plain-text"></span><br></span><span class="token-line" style="color:#bfc7d5"><span class="token plain-text"></span><span class="token tag punctuation" style="color:rgb(199, 146, 234)">&lt;/</span><span class="token tag" style="color:rgb(255, 85, 114)">picture</span><span class="token tag punctuation" style="color:rgb(199, 146, 234)">&gt;</span><br></span></code></pre><div class="buttonGroup__atx"><button type="button" aria-label="Copy code to clipboard" title="Copy" class="clean-btn"><span class="copyButtonIcons_eSgA" aria-hidden="true"><svg viewBox="0 0 24 24" class="copyButtonIcon_y97N"><path fill="currentColor" d="M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z"></path></svg><svg viewBox="0 0 24 24" class="copyButtonSuccessIcon_LjdS"><path fill="currentColor" d="M21,7L9,19L3.5,13.5L4.91,12.09L9,16.17L19.59,5.59L21,7Z"></path></svg></span></button></div></div></div>
</li>
</ul>
<p>Example result:</p>
<div aria-owns="rmiz-modal-" data-rmiz=""><div data-rmiz-content="not-found" style="visibility:visible"><picture><source srcset="/miniblog/assets/images/dv-nebia-nevia-sub-9c5bd378b2043aae9bff7710f796153e.jxl" type="image/jxl"><img src="https://saklistudio.com/miniblog/assets/images/dv-nebia-nevia-sub-c96f5f72ff0a05e44a55f86e12cbbecd.jpg" width="100%"></picture></div></div>
<p>And there you have it! <code>JPEG XL</code>-enabled Docusaurus with fallback image!</p>
<p>Spare me, I'm still a total noob in <code>node.js</code> development... I'm not even sure if those methods are safe, please <a href="https://saklistudio.com/contactme/" target="_blank" rel="noopener noreferrer">ping me</a> if you found something!</p>]]></content>
        <author>
            <name>Kampidh</name>
            <uri>https://saklistudio.com</uri>
        </author>
        <category label="JPEG XL" term="JPEG XL"/>
        <category label="coding" term="coding"/>
        <category label="hack" term="hack"/>
    </entry>
</feed>