Categories

Meta

Month: May 2013

I’ve previously produced a number of mod tools for Dune 2000 that convert colours from various formats to 24 bit and back. Although most of the source code is already online, I thought I’d share the colour conversion C# source code in one place.

Convert 15 bit high colour to 24 bit true colour

This converts 15 bit (with 1 bit padding) colour to 24 bit, by first extracting the red, green and blue channels. In 15 bit colour, each channel has 5 bits meaning 25 = 32 permutations, but we want 8 bit colour for each channel which is 28 = 256 permutations, so we divide by the highest 5 bit value and multiply by the highest 8 bit value to convert the range from 0-31 to 0-255.

C#

1

2

3

4

5

6

7

8

9

10

11

12

13

privateColor ConvertColor(UInt16 colour)

{

// bits = XRRRRRGGGGGBBBBB

bytered=(byte)((colour>>10)&0x1f);

bytegreen=(byte)((colour>>5)&0x1f);

byteblue=(byte)(colour&0x1f);

red=Convert.ToByte(255.0f*(float)red/31);

green=Convert.ToByte(255.0f*(float)green/31);

blue=Convert.ToByte(255.0f*(float)blue/31);

returnColor.FromArgb(red,green,blue);

}

Convert 24 bit true colour to 15 bit high colour

Similarly to convert to 15 bit, we convert each channel from 8 bit to 5 bit. Then we bit shift the red and green values and combine the three channels using a bitwise OR, so that we can fit all three 5 bit channels in the format XRRRRRGGGGGBBBBB.

C#

1

2

3

4

5

6

7

8

9

privateUInt16 ConvertColor(Color colour)

{

intr=(int)((colour.R/255.0f)*31)<<10;

intg=(int)((colour.G/255.0f)*31)<<5;

intb=(int)((colour.B/255.0f)*31);

intcombined=r|g|b;

returnConvert.ToUInt16(combined);

}

Convert 24 bit true colour to existing palette

This algorithm calculates the entry in an existing palette which is closest to the target colour. The algorithm treats colours as points in 3 dimensional space – instead of x,y,z we use r,g,b – and uses Euclidean Distance (the distance in a straight line between two points) to calculate the closest colour. For efficiency, all distances are kept at their square values, since it is not necessary to use the relatively expensive square root operation in distance comparisons. The assumption here is that the palette is 24 bit, however if you have a 15 bit palette you could use the conversion technique described above to convert it to a 24 bit palette.

C#

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

28

29

30

31

32

33

Color[]palette=newColor[256];

intGetNearestColorIndex(Color targetColor)

{

intindex=0;

// Set the initial color distance to the maximum

doublecurrentDistance=(255*255)*3;

Color paletteColor;

for(inti=0;i<palette.Length;i++)

{

paletteColor=palette[i];

intredDistance=paletteColor.R-targetColor.R;

intgreenDistance=paletteColor.G-targetColor.G;

intblueDistance=paletteColor.B-targetColor.B;

// Calculate the square distance from the target colour to this palette entry