Brighter Shores:Color masking

Color masking is the process that the Brighter Shores game client uses to create multiple colour variations of items without needing to render and store each individual image. Images which are recovered from the Cache of the game client give us insight into the way these images are generated. Color masking has been seen for the following types of image:

Example Edit

The process for color masking can be seen by its inputs and outputs, but the exact algorithm is not known. We can make approximations based on the resulting images that we see. Here is an example for Coarse Hickory Post, Coarse Oak Post, and Coarse Pine Post. Each type of item starts off with two images: a base image, also called a texture, and a colour mask:

The texture The mask The Hickory result The Oak result The Pine result

The texture image shows the detail of the item. Note that while the texture is not grayscale image everwhere, it is grayscale in the areas that correspond to the mask. For these posts, that is the whole image, but for Armor dyes, there is color on the non-mask sections of the image.

The mask image shows the areas where the color is to be applied. It is also monochrome, but usually not grayscale. In this example it is monochrome red, as there is only one mask to be applied. Some images, most noteable potion Preparations, have a two-color mask with a Red area and a Green area, to show two different areas which get different colors applied to them, for the two ingredients of the preparation.

For each pixel in the two input images, there are only two values: the grayscale value of the texture image, K, and the red value of the mask image, M.

The output image has a full colour for each of these pixels, so it has a red value, R, a green value, G, and a blue value, B.

There exists some color transform functions:

R=fR(K,M)
G=fG(K,M)
B=fB(K,M)

To convert the input to the output. It is important to know that there is no cache data for what these functions are.

Doing it in software Edit

In image manipulation software such as GIMP these transforms can be applied by changing the color balance, lightness, and saturation of the texture image, on the area specified by the mask image.

The above images of Coarse Posts were obtained by tweaking the values of the colour manipulation parameters until the colours of the resultant image matched a lower resolution screenshot of what the output should look like. However, once the color transform has been determined for one image, the same transform can be applied to other images. In this example, the Rugged, Average, Fine, Sturdy, and Perfect Posts for each of the 3 wood types also use the same colour transform as the Coarse Posts shown. The images created will not be perfect pixel matches to the game, but they can be close enough that people won't be able to tell the difference unless they really compare them side by side while zoomed in a lot.

What this doesn't do is allow us to know what the transformations are for an entirely new color.

Doing it in maths Edit

A close approximation of what GIMP does with the color transformation is a moderately simple function that maps the original grayscale pixel (K,K,K) toward some keystone color (R0,G0,B0), and then applies this as a semi-transparent overlay over the original image, using M as the degree of opacity.

In maths terms:

R=R0×K×M+K×(!M)
G=G0×K×M+K×(!M)
B=B0×K×M+K×(!M)

where (!M) is the complement to M, which would be (256M) for 8 bit color, or (1M) for decimal color.

So long as the keystone color (R0,G0,B0) has been correctly chosen, the color transformation of the image will give something close to what is desired.

In CSS Edit

A similar effect can be achieved in CSS by using the texture image as a background of the mask image.

<div class="outer">
  <img class="mask" src="/Coarse_Post_Mask.png" />
</div>
.outer {
  /* Just to match the width of the image */
  width: fit-content;
  
  /* Full url of the texture */
  background: url('/Coarse_Post_Texture.png');
}

.mask {
  /* Only overlay differing colors between the two images */
  mix-blend-mode: color;
  
  /* Edit the hue-rotate and other values to achieve the desired final color */
  filter: hue-rotate(0deg) brightness(1) contrast(100%) opacity(100%) saturate(100%);
}