summaryrefslogtreecommitdiff
path: root/source/blog
diff options
context:
space:
mode:
authorPrefetch2023-02-27 15:03:21 +0100
committerPrefetch2023-02-27 15:03:21 +0100
commit52ff45a7c687d502492be0fa6e54f9b99d501465 (patch)
tree202222770fe18577ba81ce6cea146e513dfe82fa /source/blog
parent75636ed8772512bdf38e3dec431888837eaddc5d (diff)
Publish "Website adventures" part 4 about images
Diffstat (limited to 'source/blog')
-rw-r--r--source/blog/2022/website-adventures-basics/index.md5
-rw-r--r--source/blog/2022/website-adventures-generators/index.md7
-rw-r--r--source/blog/2022/website-adventures-maths/index.md5
-rw-r--r--source/blog/2023/website-adventures-images/avif-reddit.avifbin0 -> 59792 bytes
-rw-r--r--source/blog/2023/website-adventures-images/index.md394
-rw-r--r--source/blog/2023/website-adventures-images/jpeg-arithmetic.jpgbin0 -> 308893 bytes
-rw-r--r--source/blog/2023/website-adventures-images/jpeg-huffman.jpgbin0 -> 339094 bytes
-rw-r--r--source/blog/2023/website-adventures-images/png-original.pngbin0 -> 1207860 bytes
-rw-r--r--source/blog/2023/website-adventures-images/png-oxipng-zopfli.pngbin0 -> 973478 bytes
-rw-r--r--source/blog/2023/website-adventures-images/png-oxipng.pngbin0 -> 982403 bytes
-rw-r--r--source/blog/2023/website-adventures-images/png-zopflipng.pngbin0 -> 975943 bytes
-rw-r--r--source/blog/2023/website-adventures-images/simulation-full.pngbin0 -> 973478 bytes
-rw-r--r--source/blog/2023/website-adventures-images/simulation-half.avifbin0 -> 27563 bytes
-rw-r--r--source/blog/2023/website-adventures-images/simulation-half.jpgbin0 -> 127051 bytes
-rw-r--r--source/blog/2023/website-adventures-images/simulation-half.pngbin0 -> 246421 bytes
-rw-r--r--source/blog/2023/website-adventures-images/simulation-half.webpbin0 -> 55982 bytes
-rw-r--r--source/blog/2023/website-adventures-images/webp-lossless.webpbin0 -> 766604 bytes
-rw-r--r--source/blog/2023/website-adventures-images/webp-lossy.webpbin0 -> 139868 bytes
-rw-r--r--source/blog/2023/website-adventures-images/webp-near-lossless.webpbin0 -> 492606 bytes
19 files changed, 404 insertions, 7 deletions
diff --git a/source/blog/2022/website-adventures-basics/index.md b/source/blog/2022/website-adventures-basics/index.md
index 64ed446..02aebef 100644
--- a/source/blog/2022/website-adventures-basics/index.md
+++ b/source/blog/2022/website-adventures-basics/index.md
@@ -5,7 +5,7 @@ layout: "blog"
toc: true
---
-Published on 2022-11-20, last updated on 2022-11-28.
+Published on 2022-11-20, last updated on 2023-02-27.
Making and managing this personal website has been an adventure.
In this series, I go over the technical challenges I've encountered
@@ -13,7 +13,8 @@ and philosophical decisions I've made,
and I review some of the tools I've used along the way.
After [part 1](/blog/2022/website-adventures-generators/),
this is part 2,
-followed by [part 3](/blog/2022/website-adventures-maths/).
+followed by [part 3](/blog/2022/website-adventures-maths/)
+and [part 4](/blog/2023/website-adventures-images/).
diff --git a/source/blog/2022/website-adventures-generators/index.md b/source/blog/2022/website-adventures-generators/index.md
index 42a6230..da7dde4 100644
--- a/source/blog/2022/website-adventures-generators/index.md
+++ b/source/blog/2022/website-adventures-generators/index.md
@@ -5,14 +5,15 @@ layout: "blog"
toc: true
---
-Published on 2022-11-15, last updated on 2022-11-28.
+Published on 2022-11-15, last updated on 2023-02-27.
Making and managing this personal website has been an adventure.
In this series, I go over the technical challenges I've encountered
and philosophical decisions I've made,
and I review some of the tools I've used along the way.
-This is part 1, followed by [part 2](/blog/2022/website-adventures-basics/)
-and [part 3](/blog/2022/website-adventures-maths/).
+This is part 1, followed by [part 2](/blog/2022/website-adventures-basics/),
+[part 3](/blog/2022/website-adventures-maths/)
+and [part 4](/blog/2023/website-adventures-images/).
diff --git a/source/blog/2022/website-adventures-maths/index.md b/source/blog/2022/website-adventures-maths/index.md
index a49b473..879a7e3 100644
--- a/source/blog/2022/website-adventures-maths/index.md
+++ b/source/blog/2022/website-adventures-maths/index.md
@@ -5,7 +5,7 @@ layout: "blog"
toc: true
---
-Published on 2022-11-28.
+Published on 2022-11-28, last updated on 2023-02-27.
Making and managing this personal website has been an adventure.
In this series, I go over the technical challenges I've encountered
@@ -13,7 +13,8 @@ and philosophical decisions I've made,
and I review some of the tools I've used along the way.
After [part 1](/blog/2022/website-adventures-generators/)
and [part 2](/blog/2022/website-adventures-basics/),
-this is part 3.
+this is part 3,
+followed by [part 4](/blog/2023/website-adventures-images/).
diff --git a/source/blog/2023/website-adventures-images/avif-reddit.avif b/source/blog/2023/website-adventures-images/avif-reddit.avif
new file mode 100644
index 0000000..686672a
--- /dev/null
+++ b/source/blog/2023/website-adventures-images/avif-reddit.avif
Binary files differ
diff --git a/source/blog/2023/website-adventures-images/index.md b/source/blog/2023/website-adventures-images/index.md
new file mode 100644
index 0000000..d678362
--- /dev/null
+++ b/source/blog/2023/website-adventures-images/index.md
@@ -0,0 +1,394 @@
+---
+title: "Adventures in making this website:<br>image optimization"
+date: 2023-02-27
+layout: "blog"
+toc: true
+---
+
+Published on 2023-02-27.
+
+Making and managing this personal website has been an adventure.
+In this series, I go over the technical challenges I've encountered
+and philosophical decisions I've made,
+and I review some of the tools I've used along the way.
+After [part 1](/blog/2022/website-adventures-generators/),
+[part 2](/blog/2022/website-adventures-basics/)
+and [part 3](/blog/2022/website-adventures-maths/),
+this is part 4.
+
+
+
+## Principles
+
+After some consideration,
+I settled on the following five commandments of image optimization
+for this website:
+
+1. **Provide the originals.**
+ If any scaling or lossy compression has been done
+ on an image displayed on the page,
+ wrap it in `<a>` linking to the full-size lossless original file.
+
+2. **Prioritize quality**.
+ My server provider doesn't charge me for traffic,
+ and there aren't many images on this website,
+ so I can afford to keep the quality high.
+ The degradation of an 80% JPEG compared to 90%
+ isn't worth it just to save a few kilobytes.
+ You should do your own tests to decide what quality
+ is acceptable for the kind of images you have.
+
+3. **Limit the resolutions.**
+ It's wasteful to use a 2000px wide image
+ if it's only 200px wide on a user's screen.
+ I use the following rules to choose resolutions:
+
+ 1. If an image is `W`px wide my screen,
+ its resolution should be roughly `1.5*W`px:
+ a 50% surplus is friendly to high-DPI screens,
+ and prevents scaling artefacts.
+ This rule also works in reverse:
+ if I have an `X`px file for whatever reason,
+ its scale should be chosen such that it takes up around `0.67*X`px on my screen.
+
+ 2. Because my website's `<body>` is ~720px wide for me,
+ the largest sensible image width is ~1080px.
+ But sometimes more is needed to show all details:
+ in that case, display a downscaled image on the page,
+ linking to the original.
+ When downscaling, always divide the width and height
+ by an integer divisor of both.
+
+4. **Use modern formats.**
+ The JPEG standard was released in 1992,
+ and in the three decades since then,
+ a lot of research has been done in image and video compression.
+ If a modern format can shrink files by 75%
+ with little to no change in quality, why wouldn't I use it?
+
+5. **Maintain compatibility.**
+ Modern image formats are great, but some are so modern
+ that almost nobody can use them, so fallbacks should be provided.
+ Fortunately, HTML has a built-in way to do this, see below.
+
+The HTML `<picture>` tag can be used to provide multiple formats
+depending on what the browser supports,
+or multiple resolutions depending on the user's screen size
+(I don't use this feature as of writing).
+`<picture>` is supported by all modern browsers,
+but obviously [not IE11](https://caniuse.com/picture),
+although that doesn't matter, because backwards compatibility is baked into it!
+Here it is:
+
+```html
+<!-- I wrap the whole image in a link to the original file -->
+<a href="file.png">
+ <picture>
+ <!-- Various image source files are listed in order of preference:
+ the browser will use whichever one fulfills its conditions first. -->
+ <source srcset="file.avif" type="image/avif">
+ <!-- Each `<source>` should include the MIME type, so the browser
+ can know which format it is without needing to download the file. -->
+ <source srcset="file.webp" type="image/webp">
+ <!-- If no `<source>` is suitable, or the browser doesn't support
+ `<picture>`, a traditional `<img>` at the bottom is used instead. -->
+ <img src="file.jpg" alt="..." title="...">
+ <!-- Other attributes like `alt` and inline CSS are always taken
+ from `<img>`, even if a `<source>` tag is used to fetch the file. -->
+ </picture>
+</a>
+```
+
+To automate rules 1, 3, 4 and 5, I wrote a Jekyll template:
+[`image.html`](/code/prefetch-jekyll/tree/source/_includes/image.html).
+To handle rule 3 there's a bit of logic, but the idea is as follows:
+
+* If the file is small enough not to need downscaling,
+ provide an AVIF and the original JPEG or PNG (in that order).
+ In my testing, WebP didn't help much for such tiny images.
+* For larger images, the full-size file ends in `-full`,
+ and the half-size file in `-half`. The template detects this,
+ and then displays the downscaled AVIF, WebP and JPEG versions,
+ wrapped in a link to the original PNG/JPEG.
+
+Let me tell you how I squeezed every drop out of those PNG, JPEG, WebP and AVIF files.
+
+
+
+## Optimizing each format
+
+I will use the test image given below, which shows a simulation of
+[modulational instability](/know/concept/modulational-instability/)
+in an optical fiber.
+The raw file, as exported by [Veusz](https://veusz.github.io/),
+is a 1,207,860-byte (1.21MB, 1.15MiB) PNG
+with a resolution of 2362x1062, or 2,508,444px&sup2; (2.51MP).
+Click for lossless full-size view:
+
+{% include image.html file="simulation-full.png"
+ width="100%" alt="Modulational instability simulation results" %}
+
+This is representative of the kind of pictures I have on this website,
+and it has a combination of high-contrast text and lines, gradual colour transitions,
+and fine details (especially at the top of the left panel).
+Depending on what images you want to optimize,
+your mileage may vary if you take my advice.
+Figure out what works for you, and I hope this post helps with that.
+
+
+
+### PNG
+
+Despite dating from the late 1990s,
+[PNG](https://en.wikipedia.org/wiki/PNG) is still pretty solid.
+Its losslessness makes it by far the largest format discussed here,
+but it would be unfair to hold that against it.
+For full quality, PNG is the perfect choice
+before more exotic formats like TIFF.
+
+But not all lossless compression is the same.
+Given a PNG image, you may be able to reduce its size
+using [Oxipng](https://github.com/shssoichiro/oxipng),
+which plays with the file's internal knobs
+to squeeze every last drop out of the compression algorithms.
+Let's dial all settings to eleven and see what it can do:
+
+```sh
+$ oxipng --strip=all --alpha --filters=9 --zc=12 image.png
+# 1,207,860 to 982,403 bytes: reduced by 225,457 bytes (18.7%)
+# Took 2s on my system (oxipng 8.0.0)
+```
+
+A 16.4% reduction for losslessly compressed data is pretty impressive.
+`--strip=all` removes all unneeded metadata,
+`--alpha` enables transparency optimizations,
+e.g. removing the A channel from an opaque RGBA image,
+and `--zc=12` sets the highest [Deflate](https://en.wikipedia.org/wiki/Deflate) level.
+
+`--filters=9` tells Oxipng to brute-force the PNG's per-row
+[filtering](https://en.wikipedia.org/wiki/PNG#Filtering) setting,
+which always gave the best results in my tests.
+I you want, you can instead use `--opt=max` to try all filtering approaches
+(including `9`): this is slower, but may be better for some images?
+I'm not sure.
+
+But can we go smaller? Yes, in fact we can, although it comes at a cost.
+Yes, that's over 2 minutes to optimize a single 2.5MP image:
+
+```sh
+$ oxipng --strip=all --alpha --filters=9 --zopfli image.png
+# 1,207,860 to 973,478 bytes: reduced by 234,382 bytes (19.4%)
+# Took 2m9s on my system (oxipng 8.0.0)
+```
+
+So what does `--zopfli` do? Well, [Zopfli](https://github.com/google/zopfli)
+is a Google-made compressor aiming to minimize file sizes
+while being Deflate-compatible.
+Basically, it's [zlib](https://zlib.net/) but better.
+Interestingly, Zopfli ships with its own PNG optimizer `zopflipng`...
+Let's see what it can do:
+
+```sh
+$ zopflipng --iterations=15 --filters=b -y input.png output.png
+# 1,207,860 to 975,943 bytes: reduced by 231,917 bytes (19.2%)
+# Took 1m3s on my system (zopfli 1.0.3)
+```
+
+You can increase the number of iterations if you want to,
+but the returns diminish strongly,
+and it wasn't enough to beat Oxipng in a reasonable time.
+Time is the key word:
+no, `zopflipng` doesn't beat Oxipng's Zopfli mode,
+but it does save a lot of time!
+
+File links:
+[original PNG](png-original.png),
+[Oxipng (no Zopfli)](png-oxipng.png),
+[Oxipng (Zopfli)](png-oxipng-zopfli.png),
+[Zopflipng](png-zopflipng.png),
+
+
+
+### JPEG
+
+While PNG has held up well, [JPEG](https://en.wikipedia.org/wiki/JPEG) hasn't really.
+It's the most popular lossy compression format,
+but its distinctive damage to the image's quality
+is worse than modern alternatives,
+and high-quality JPEGs tend to be quite large.
+
+Figuring out how to optimize JPEGs is easy,
+because someone else has already done the hard work for us:
+[MozJPEG](https://github.com/mozilla/mozjpeg)
+is a [friendly fork](https://libjpeg-turbo.org/About/Mozjpeg)
+of the popular `libjpeg-turbo` package,
+where Mozilla uses all the latest tech to make small, good-looking JPEGs:
+
+```sh
+$ cjpeg -quality 90 -outfile output.jpg input.png
+# 1,207,860 to lossy 339,094 bytes: reduced by 868,766 bytes (71.9%)
+# Took 0.2s on my system (MozJPEG 4.1.1)
+```
+
+But what if you don't have a PNG, only a non-optimized JPEG?
+Then you can choose between:
+
+```sh
+$ jpegtran -copy none -outfile output.jpg input.jpg
+$ jpegoptim --strip-all image.jpg # separate package
+```
+
+And as long as you have MozJPEG installed,
+these will squeeze every drop out of your file.
+If you can't use MozJPEG for some reason,
+`jpegoptim` can still help a bit.
+
+If you're feeling adventurous, you can pass the `-arithmetic` flag
+to `cjpeg` or `jpegtran` to employ [arithmetic coding](https://en.wikipedia.org/wiki/Arithmetic_coding)
+instead of [Huffman coding](https://en.wikipedia.org/wiki/Huffman_coding),
+which knocks a few percent off the size:
+
+```sh
+# Don't actually do this!
+$ cjpeg -quality 90 -arithmetic -outfile output.jpg input.png
+# 1,207,860 to lossy 308,893 bytes: reduced by 898,967 bytes (74.4%)
+# Took 0.4s on my system (MozJPEG 4.1.1)
+```
+
+The problem is that many image viewers (including browsers)
+can't display these files because arithmetic coding was patented,
+so implementations couldn't just be freely distributed or used.
+The patents have expired now, but the world hasn't caught up yet.
+
+File links:
+[normal JPEG](jpeg-huffman.jpg),
+[arithmetic JPEG](jpeg-arithmetic.jpg).
+Bonus points if you can open the latter.
+
+
+
+### WebP
+
+[WebP](https://en.wikipedia.org/wiki/WebP) is the Swiss army knife of formats,
+supporting both lossless and lossy compression of static or animated images.
+It's only been around for a few years, and hasn't gained so much popularity,
+probably because it was immediately overshadowed by AVIF (to be discussed below).
+Internally, it relies on VP8 video compression:
+this provides a nice size reduction,
+but the images tend to get blurred slightly,
+and low-contrast areas can become blocky.
+
+Indeed high-quality JPEGs look better than high-quality WebPs,
+but the latter tend to be less than half the size, so it isn't bad at all.
+According to my tests, the best way to create a WebP is:
+
+```sh
+$ cwebp -q 90 -m 6 -sharp_yuv -sns 100 input.png -o output.webp
+# 1,207,860 to lossy 139,868 bytes: reduced by 1,067,992 bytes (88.4%)
+# Took 0.3s on my system (libwebp 1.3.0, libsharpyuv 0.2.0)
+```
+
+The flags `-q 90` and `-m 6` set the quality to 90%
+with the slowest compression method.
+The most important setting is `-sharp_yuv`,
+which counteracts a lot of the blurriness
+and more accurately preserves the contrast,
+at the cost of slightly larger files.
+`-sns 100` has a big effect on file size, without much influence on quality.
+
+I don't use WebP's lossless mode, but according to
+[this post](https://siipo.la/blog/whats-the-best-lossless-image-format-comparing-png-webp-avif-and-jpeg-xl)
+it's one of the best out there, so I had a quick look,
+and it's indeed pretty impressive compared to PNG:
+
+```sh
+$ cwebp -lossless -z 9 input.png -o output.webp
+# 1,207,860 to 766,604 bytes: reduced by 441,256 bytes (36.5%)
+# Took 7.2s on my system (libwebp 1.3.0)
+```
+
+You can also pass `-near_lossless 0` to let it slightly change
+pixel values for better compressibility.
+This causes visible degradation, but still looks better than a lossy-mode WebP:
+
+```sh
+$ cwebp -lossless -near_lossless 0 -z 9 input.png -o output.webp
+# 1,207,860 to 492,606 bytes: reduced by 715,254 bytes (59.2%)
+# Took 6.6s on my system (libwebp 1.3.0)
+```
+
+File links:
+[lossy WebP](webp-lossy.webp),
+[lossless WebP](webp-lossless.webp),
+[near-lossless WebP](webp-near-lossless.webp).
+
+
+
+### AVIF
+
+[AVIF](https://en.wikipedia.org/wiki/AVIF),
+the new kid on the block based on [AV1](https://en.wikipedia.org/wiki/AV1) video compression,
+is honestly incredible:
+it reduces file sizes much further than WebP,
+and the final quality is so good that I sometimes struggled
+to tell the difference with the original PNG.
+I suspect that AVIF's success is the reason why Google is winding down
+their work on [WebP 2](https://en.wikipedia.org/wiki/WebP#WebP_2)
+and [JPEG-XL](https://en.wikipedia.org/wiki/JPEG_XL#Preliminary_web_browser_support).
+
+AV1 compression is complicated business,
+so I haven't exhaustively tested all options as I did for JPEG and WebP.
+Instead, I used the settings I found in
+[this Reddit post](https://www.reddit.com/r/AV1/comments/o7s8hk/high_quality_encoding_of_avif_images_using/),
+because I trust random strangers on the Internet:
+
+```sh
+$ avifenc --min 0 --max 63 --speed 0 -a end-usage=q -a cq-level=31 -a color:sharpness=2 \
+ -a tune=ssim -a color:enable-chroma-deltaq=1 -a color:deltaq-mode=3 -a color:aq-mode=1 \
+ input.png output.avif
+# 1,207,860 to lossy 59,792 bytes: reduced by 1,148,068 bytes (95.1%)
+# Took 11s on my system (libavif 0.11.1)
+```
+
+Yes, it's slower to encode, and you can see some degradation if you look closely,
+but that's a 95% compression ratio!
+It looks slightly worse than the JPEG from earlier (which was 5 times as big),
+but better than the lossy WebP (which was over twice the size).
+Incredible.
+
+AVIF is quite new, so support is still lacking.
+As of writing, Firefox and Chromium work perfectly, but Edge can't display AVIFs yet,
+and if I try to open a file with [`imv`](https://sr.ht/~exec64/imv/), it looks messed up.
+
+File links:
+[lossy AVIF](avif-reddit.avif).
+
+
+
+### JPEG-XL
+
+As of writing, Firefox can't display JPEG-XL yet, and Google has
+[aborted support](https://bugs.chromium.org/p/chromium/issues/detail?id=1178058#c84) for it.
+If it doesn't work on the web and I can't even test it locally,
+then I definitely can't optimize it!
+
+It's sad, because there's evidence
+(e.g. in [this post](https://chipsandcheese.com/2021/02/28/modern-data-compression-in-2021-part-2-the-battle-to-dethrone-jpeg-with-jpeg-xl-avif-and-webp/))
+that JPEG-XL is a significant improvement over AVIF
+in every way: fidelity, file size, and encoding/decoding speed,
+although the latter might be due to AV1's relative immaturity.
+It can also losslessly recompress existing JPEGs!
+
+
+
+## Conclusion
+
+Of course, optimizing images is optional,
+but doing so speeds up page loading for users on bad connections,
+and, if your server provider bills you for traffic,
+can save you a significant amount of money too.
+My website doesn't contain many images, but on the pages that do,
+using a modern format like AVIF reduces transfers by >80% compared to JPEG,
+which has been the standard for far too long.
+WebP isn't as good as AVIF, but is also a respectable choice.
+JPEG-XL would be the best of all words, but sadly doesn't seem meant to be.
diff --git a/source/blog/2023/website-adventures-images/jpeg-arithmetic.jpg b/source/blog/2023/website-adventures-images/jpeg-arithmetic.jpg
new file mode 100644
index 0000000..eb19de6
--- /dev/null
+++ b/source/blog/2023/website-adventures-images/jpeg-arithmetic.jpg
Binary files differ
diff --git a/source/blog/2023/website-adventures-images/jpeg-huffman.jpg b/source/blog/2023/website-adventures-images/jpeg-huffman.jpg
new file mode 100644
index 0000000..3c1e9fa
--- /dev/null
+++ b/source/blog/2023/website-adventures-images/jpeg-huffman.jpg
Binary files differ
diff --git a/source/blog/2023/website-adventures-images/png-original.png b/source/blog/2023/website-adventures-images/png-original.png
new file mode 100644
index 0000000..d8812c1
--- /dev/null
+++ b/source/blog/2023/website-adventures-images/png-original.png
Binary files differ
diff --git a/source/blog/2023/website-adventures-images/png-oxipng-zopfli.png b/source/blog/2023/website-adventures-images/png-oxipng-zopfli.png
new file mode 100644
index 0000000..ebbca6c
--- /dev/null
+++ b/source/blog/2023/website-adventures-images/png-oxipng-zopfli.png
Binary files differ
diff --git a/source/blog/2023/website-adventures-images/png-oxipng.png b/source/blog/2023/website-adventures-images/png-oxipng.png
new file mode 100644
index 0000000..06fb22f
--- /dev/null
+++ b/source/blog/2023/website-adventures-images/png-oxipng.png
Binary files differ
diff --git a/source/blog/2023/website-adventures-images/png-zopflipng.png b/source/blog/2023/website-adventures-images/png-zopflipng.png
new file mode 100644
index 0000000..ecb9ede
--- /dev/null
+++ b/source/blog/2023/website-adventures-images/png-zopflipng.png
Binary files differ
diff --git a/source/blog/2023/website-adventures-images/simulation-full.png b/source/blog/2023/website-adventures-images/simulation-full.png
new file mode 100644
index 0000000..ebbca6c
--- /dev/null
+++ b/source/blog/2023/website-adventures-images/simulation-full.png
Binary files differ
diff --git a/source/blog/2023/website-adventures-images/simulation-half.avif b/source/blog/2023/website-adventures-images/simulation-half.avif
new file mode 100644
index 0000000..9f0f5cf
--- /dev/null
+++ b/source/blog/2023/website-adventures-images/simulation-half.avif
Binary files differ
diff --git a/source/blog/2023/website-adventures-images/simulation-half.jpg b/source/blog/2023/website-adventures-images/simulation-half.jpg
new file mode 100644
index 0000000..e1cc716
--- /dev/null
+++ b/source/blog/2023/website-adventures-images/simulation-half.jpg
Binary files differ
diff --git a/source/blog/2023/website-adventures-images/simulation-half.png b/source/blog/2023/website-adventures-images/simulation-half.png
new file mode 100644
index 0000000..d4cb347
--- /dev/null
+++ b/source/blog/2023/website-adventures-images/simulation-half.png
Binary files differ
diff --git a/source/blog/2023/website-adventures-images/simulation-half.webp b/source/blog/2023/website-adventures-images/simulation-half.webp
new file mode 100644
index 0000000..d2a0edb
--- /dev/null
+++ b/source/blog/2023/website-adventures-images/simulation-half.webp
Binary files differ
diff --git a/source/blog/2023/website-adventures-images/webp-lossless.webp b/source/blog/2023/website-adventures-images/webp-lossless.webp
new file mode 100644
index 0000000..8579535
--- /dev/null
+++ b/source/blog/2023/website-adventures-images/webp-lossless.webp
Binary files differ
diff --git a/source/blog/2023/website-adventures-images/webp-lossy.webp b/source/blog/2023/website-adventures-images/webp-lossy.webp
new file mode 100644
index 0000000..c8e541b
--- /dev/null
+++ b/source/blog/2023/website-adventures-images/webp-lossy.webp
Binary files differ
diff --git a/source/blog/2023/website-adventures-images/webp-near-lossless.webp b/source/blog/2023/website-adventures-images/webp-near-lossless.webp
new file mode 100644
index 0000000..b6e1d3c
--- /dev/null
+++ b/source/blog/2023/website-adventures-images/webp-near-lossless.webp
Binary files differ