srgb.go LinearToSRGB8 maybe incorrect?
Closed this issue · 1 comments
Below is modified version of LinearToSRGB8 and a use case for generating mipmaps. I double-checked the code is transcribed correctly (could be wrong of course) and the first test I did has li
equal to 23,566,590 that's said to be out of the range (see the //comments) of divsqr257rnd and produces a value larger than 255 (357). The input (from the mipmap) is 248. The input to LinearToSRGB8 is 61517 (f04d). I think there must be an error. I've read every letter of the code 3 or 4 times, but please by all means check my work.
For the record, the resulting image is bright and littered with glitches.
static BYTE Ex_mipmap_LinearToSRGB8(WORD lin)
{
// piecewise linear
//div, mod := divmod257(uint32(lin))
DWORD div,mod;
{
// valid for x=[0..256*65535[
QWORD mul = QWORD(lin)*0xff0100;
mod = mul*257>>32;
div = mul>>32;
}
DWORD l0 = Ex_mipmap_l8s16[(BYTE)(div)];
DWORD l1 = Ex_mipmap_l8s16[(BYTE)(div+1)];
DWORD li = 257*l0+mod*(l1-l0);
//return uint8(divsqr257rnd(li))
{
// valid for x=[0..257*65535[
QWORD mul = QWORD(li+0x8100)*0x1fc05f9;
div = mul>>41;
return (BYTE)div;
}
}
extern BYTE Ex_mipmap_sRGB(DWORD b4)
{
DWORD sum = 0;
for(int i=4;i-->0;b4>>=8)
sum+=Ex_mipmap_s8l16[b4&0xFF];
sum/=4;
return Ex_mipmap_LinearToSRGB8((WORD)sum);
}
Oh yes, I remembered some casts, and thought they might be truncating. Sorry for a false flag. Maybe 0xFFFFFFFF&mul is a better way to write truncation with all of the casting going on in this code, maybe to satisfy diagnostics. Below is my code with changes:
mod = QWORD((DWORD)mul)*257>>32;
P.S. Thanks for code! It's very helpful 👍