Skip to content
This repository has been archived by the owner on Nov 26, 2022. It is now read-only.

Invalid color component interpolation from x-bit to 8-bit representation #26

Open
MetLob opened this issue Feb 20, 2016 · 3 comments
Open

Comments

@MetLob
Copy link
Contributor

MetLob commented Feb 20, 2016

Hi
To restore color componetnt (R, G, B or A) from x-bit representation (RGB555 for example, x = 5) we need max value (0x1F) convert to 0xFF - max value for 8-bit color.

You use formula: C(R/G/B/A) * 8 - is incorrect.

Nvidia Texture tools and squish using the next formula for restore x-bit color component (Cx) to 8-bit representation (C8) (for x >= 4)
C8 = (Cx << (8 - x)) | (Cx >> (x - (8 - x)));

This formula hardest if x < 4 (and for all cases):
C8 = Sum(Cx << (8 - i * x)); // while i * x < 4
C8 |= Cx >> x - (8 - last(i) * x));

for 5-bit representation of Red component this formula have view: R = (R << 3) | (R >> 2);
for 6-bit representation of Green component this formula have view: G = (G << 2) | (G >> 4);
for 3-bit representaion of Alpha: A = (A << 5) | (A << 2) | (A >> 1);

Nvidia Texture tools in last version optimize method for fast RGB565 convert:

static Color32 bitexpand_color16_to_color32(Color16 c16) {
Color32 c32;
//c32.b = (c16.b << 3) | (c16.b >> 2);
//c32.g = (c16.g << 2) | (c16.g >> 4);
//c32.r = (c16.r << 3) | (c16.r >> 2);
//c32.a = 0xFF;

c32.u = ((c16.u << 3) & 0xf8) | ((c16.u << 5) & 0xfc00) | ((c16.u << 8) & 0xf80000);
c32.u |= (c32.u >> 5) & 0x070007;
c32.u |= (c32.u >> 6) & 0x000300;

return c32;
}

ImageLib using next formula for all cases:
C8 = Cx * 255 / max(Cx); where max(Cx) = (2^x) - 1 or max = (1 << x) - 1;

for 5-bit representation of Red: R = R * 255 / 31;
for 3-bit representaion of Alpha: A = A * 255 / 7;
for 4-bit representaion of Alpha: A = A * 255 / 15; // A *= 17;

You need to fix this in next methods and classes:
Ekona/Images/Actions.cs
public static Color BGR555ToColor(byte byte1, byte byte2)
public static Byte[] AlphaIndexTo32ARGB(Color[] palette, byte[] data, ColorFormat format) // for alpha parameter
public static Color Get_Color(Byte[] data, Color[] palette, ColorFormat format, ref int pos)

Plugins/3DModels/3DModels/BTX0.cs
private static Bitmap Draw_Texture(IPluginHost pluginHost, sBTX0 btx0, byte[] data, sBTX0.Texture.TextInfo info, Color[] palette)

@MetLob MetLob changed the title Invalid color component conversion from x-bit to 8-bit representation Invalid color component interpolation from x-bit to 8-bit representation Feb 20, 2016
@pleonex pleonex added the bug label Feb 28, 2016
@pleonex
Copy link
Owner

pleonex commented Feb 28, 2016

In what cases the current implementation of multiplying by 8 gives an incorrect result? I mean, to expand the range [0, 32) to [0, 256) it can be done by multiplying by 256/32 = 8. This can be done in bitwise operations by shifting to the left 3 like (r <<= 3).

If we are going to modify the conversion BGR555 to Color, we may need to fix the reverse Color to BGR555 too.

@MetLob
Copy link
Contributor Author

MetLob commented Mar 1, 2016

Yea, simple multiplying by 8 expand 31 to 0xF8, but we must get 0xFF. This is true.
For correct expand 31 to 255 we must multiplying by 255 in begin and divide by 31 after. Or use bitwise operations.

For reverse Color to BGR555 in this fix not necessary. Because we divided to 8 (for example) in integer format and get one value from 0xF8 to 0xFF of originals values.

@pleonex pleonex added core and removed unconfirmed labels Mar 10, 2016
@pleonex
Copy link
Owner

pleonex commented Mar 10, 2016

I see now, yes, you are right. Since 31 is the highest intensity for a color component in 5 bits, when expanded to 8 bits it must also be the highest one, which is 255.

@pleonex pleonex added this to the v0.9.2 milestone Jun 3, 2016
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Projects
None yet
Development

No branches or pull requests

2 participants