Automatically picking the best ASTC textures quality



This content originally appeared on DEV Community and was authored by keaukraine

In this small article I’ll describe the simple script I’ve created while working on the Cartoon Lighthouse live wallpaper. You can find a live web demo of this app here and take a look at its source code here.

I’ve encountered a slight problem with encoding 31 textures into ASTC format. The thing is that usually in all our apps geometries are batched and merged to reduce the amount of draw calls. So typically we use a couple of large texture atlases for all geometries. In this scene however geometries were not batched and I decided to keep this as is since the total amount of draw calls is still rather small (around 30). So this resulted in 31 textures which were to be converted into ASTC format.

So usually I just encoded textures with some ASTC block sizes (4×4, 6×6, 8×8 and 10×10) and manually picked the one which looked good enough for my liking. While this was OK for a handful of textures it was quite a cumbersome process for 31 ones. This needed some automation, and fortunately I’ve encountered this wonderful tweet about quality improvements of Spark realtime texture encoder (make sure to check it out, the project is fascinating by itself). What was interesting in it for me is the usage of a tool called SSIMULACRA2. This open-source tool compares two images and gives it a quality score. And the algorithm is specifically tuned to look for both user-perceived and blocky compression-related artifacts in the images! That’s exactly what I needed!

Over the weekend I’ve created a bash script (bash is not my native language so I’ve used ChatGPT to help me here and there) and tested it. The algorithm of the script can be described with this pseudocode:

for each input file  
    for each ASTC block size from the lowest to the highest quality  
        encode image and save its decoded image  
        compare quality between original and decoded images  
        if quality is within threshold encode with this block size

You can optionally specify SSIMULACRA2 score but the default is 70 which can be described as “there are some compression artifacts if you look for them specifically”.

There’s additional logic for the detection of mipmaps – these must be encoded with the same compression so only the highest level is tested for quality.

There’s a limitation of the SSIMULACRA2 tool – it doesn’t validate images smaller than 8×8 pixels so these are encoded with fallback 4×4 block size.

Also I’ve played around with bash output a little so it is not so silent while working – it informs how it processes the current image, and shows scores for the processed images:

This saved not only my time – I didn’t have to check the quality of each file manually – but file sizes too! Because of my laziness I checked manually only a subset of ASTC block sizes but this script relentlessly runs through all 14 blocks supported by ASTC, choosing the best suitable one. And for some smallish textures with quite uniform images even 12×12 block size was good enough.

You can check the source code of the script here on the GitHub and adapt it for your needs. Also it has an imagemagick script to create mip maps.


This content originally appeared on DEV Community and was authored by keaukraine