From 223b3d1921902f4be1bea7e33dc9a48a4e134d2e Mon Sep 17 00:00:00 2001 From: Rangi <35663410+Rangi42@users.noreply.github.com> Date: Mon, 8 Sep 2025 15:13:25 -0400 Subject: [PATCH] More accurate 8-bit <=> 5-bit RGB color conversion (#1827) --- include/gfx/rgba.hpp | 5 +---- man/rgbasm-old.5 | 18 ++++++++++++++++++ src/gfx/rgba.cpp | 7 ++++--- test/gfx/alpha_embedded.err | 4 ++-- test/gfx/at-file-ref.err | 2 +- test/gfx/bad_manual_pals.err | 4 ++-- test/gfx/base_ids.out.pal | Bin 32 -> 32 bytes test/gfx/bg_fuse.err | 2 +- test/gfx/bg_fuse.png | Bin 177 -> 174 bytes test/gfx/empty_lines.out.pal | 2 +- test/gfx/full_aco.out.pal | Bin 64 -> 64 bytes test/gfx/full_aco.png | Bin 927 -> 556 bytes test/gfx/full_act.out.pal | Bin 64 -> 64 bytes test/gfx/full_act.png | Bin 927 -> 556 bytes test/gfx/full_gpl.out.pal | Bin 64 -> 64 bytes test/gfx/full_gpl.png | Bin 927 -> 556 bytes test/gfx/full_psp.out.pal | Bin 64 -> 64 bytes test/gfx/full_psp.png | Bin 927 -> 556 bytes test/gfx/interlaced.out.pal | Bin 64 -> 64 bytes test/gfx/randtilegen.cpp | 2 +- 20 files changed, 31 insertions(+), 15 deletions(-) diff --git a/include/gfx/rgba.hpp b/include/gfx/rgba.hpp index b86968b9..3d5e1a45 100644 --- a/include/gfx/rgba.hpp +++ b/include/gfx/rgba.hpp @@ -18,10 +18,7 @@ struct Rgba { : red(rgba >> 24), green(rgba >> 16), blue(rgba >> 8), alpha(rgba) {} static constexpr Rgba fromCGBColor(uint16_t color) { - constexpr auto _5to8 = [](uint8_t channel) -> uint8_t { - channel &= 0b11111; // For caller's convenience - return channel << 3 | channel >> 2; - }; + constexpr auto _5to8 = [](uint8_t c) -> uint8_t { return ((c & 0b11111) * 255 + 15) / 31; }; return { _5to8(color), _5to8(color >> 5), diff --git a/man/rgbasm-old.5 b/man/rgbasm-old.5 index 86624bd7..dc209790 100644 --- a/man/rgbasm-old.5 +++ b/man/rgbasm-old.5 @@ -461,6 +461,24 @@ Previously we had .Pp Instead, now we have .Ql p ** q ** r == p ** (q ** r) . +.Ss 8-bit and 5-bit color conversion +Changed in 1.0.0. +.Pp +RGBGFX takes 8-bit RGB colors as its PNG input, and outputs 5-bit GBC colors. +Its +.Ql -r/--reverse +mode does the opposite 5-bit to 8-bit conversion. +Instead of the previous inaccurate conversions, we now do accurate rounding to the nearest equivalent. +.Pp +Previously to convert an 8-bit color channel to 5-bit, we truncated it as +.Ql c >> 3 ; +and to reverse a 5-bit color channel to 8-bit, we extended it as +.Ql (c << 3) | (c >> 2) . +.Pp +Instead, now we round 8-bit to 5-bit as +.Ql (c * 31 + 127) / 255 , +and round 5-bit to 8-bit as +.Ql (c * 255 + 15) / 31 . .Sh BUGS These are misfeatures that may have been possible by mistake. They do not get deprecated, just fixed. diff --git a/src/gfx/rgba.cpp b/src/gfx/rgba.cpp index ef37eace..e3f54cc1 100644 --- a/src/gfx/rgba.cpp +++ b/src/gfx/rgba.cpp @@ -50,9 +50,10 @@ uint16_t Rgba::cgbColor() const { g = reverse_curve[g]; b = reverse_curve[b]; } else { - r >>= 3; - g >>= 3; - b >>= 3; + constexpr auto _8to5 = [](uint8_t c) -> uint8_t { return (c * 31 + 127) / 255; }; + r = _8to5(r); + g = _8to5(g); + b = _8to5(b); } return r | g << 5 | b << 10; } diff --git a/test/gfx/alpha_embedded.err b/test/gfx/alpha_embedded.err index 8efb02a9..d5ecfd17 100644 --- a/test/gfx/alpha_embedded.err +++ b/test/gfx/alpha_embedded.err @@ -1,4 +1,4 @@ -error: Failed to fit tile colors [$1527, $15cc, $1ab4] in specified palettes +error: Failed to fit tile colors [$1527, $15cc, $1a93] in specified palettes note: The following palette was specified: - [$1ab4, $15cc] + [$1a93, $15cc] Conversion aborted after 1 error diff --git a/test/gfx/at-file-ref.err b/test/gfx/at-file-ref.err index f480fa6e..2de5a93f 100644 --- a/test/gfx/at-file-ref.err +++ b/test/gfx/at-file-ref.err @@ -1,4 +1,4 @@ -error: Failed to fit tile colors [$6c8a, $7f55, $7fff] in specified palettes +error: Failed to fit tile colors [$688b, $7f55, $7fff] in specified palettes note: The following palettes were specified: [$5f77, $213d, $41a6, $40ee] [$3f65, $36b3, $262a, $50b0] diff --git a/test/gfx/bad_manual_pals.err b/test/gfx/bad_manual_pals.err index 0815a1ff..8817b39c 100644 --- a/test/gfx/bad_manual_pals.err +++ b/test/gfx/bad_manual_pals.err @@ -1,5 +1,5 @@ -error: Failed to fit tile colors [$6c8a, $7f55, $7fff] in specified palettes +error: Failed to fit tile colors [$688b, $7f55, $7fff] in specified palettes note: The following palettes were specified: [$7fff, $7f55] - [$7fff, $6c8a] + [$7fff, $688b] Conversion aborted after 1 error diff --git a/test/gfx/base_ids.out.pal b/test/gfx/base_ids.out.pal index 6baa19cf789541fac6ea724f1b9d58b36a18f41c..e431fa47c6f575c3879697b8363f3a4faad84730 100644 GIT binary patch literal 32 ocma!N-p?q{z`*d0`GIh&83V)r`Umw6bqi|#*URUK)o|7T0Ir1#zyJUM literal 32 ncmb*aIAYB*~Eu`vt3 diff --git a/test/gfx/bg_fuse.err b/test/gfx/bg_fuse.err index ecbbd45c..47d61d0f 100644 --- a/test/gfx/bg_fuse.err +++ b/test/gfx/bg_fuse.err @@ -1,3 +1,3 @@ -warning: Fusing colors #a9b9c9ff and #aabbccff into Game Boy color $66f5 [first seen at x: 1, y: 1] +warning: Fusing colors #a9bacbff and #aabbccff into Game Boy color $66f5 [first seen at x: 1, y: 1] FATAL: Tile (0, 0) contains the background color (#aabbccff)! Conversion aborted after 1 error diff --git a/test/gfx/bg_fuse.png b/test/gfx/bg_fuse.png index 2fee135f8b779cb32f9a732c69a525b78302cab1..e48fb6e2260425ea0f577789f32437043c42b6e7 100644 GIT binary patch delta 53 zcmdnUxQ=mx3KwH>kh>GZx^prwCmO17?Dk8Z%2RH9bYiT7h{FqUlPtT+T?|0r>FVdQ I&MBb@0O`pe5KjOA diff --git a/test/gfx/empty_lines.out.pal b/test/gfx/empty_lines.out.pal index ca034125..61337e6c 100644 --- a/test/gfx/empty_lines.out.pal +++ b/test/gfx/empty_lines.out.pal @@ -1 +1 @@ -ŠlU˙˙˙ \ No newline at end of file +‹hU˙˙˙ \ No newline at end of file diff --git a/test/gfx/full_aco.out.pal b/test/gfx/full_aco.out.pal index 820ff240b205aca691f9695ec6f9e47fe58a6006..45edb6b8d952d69c0d386c071774c551866c388a 100644 GIT binary patch literal 64 zcmZQz_+KwkZk(6ndDNg;Vt)9~FcG&(S0mH=PSSSUOy%@r^ma&^+ON?&6~=1ktean* UUAL-`Ei@qWwa5QFnWU0P0Ps*3(*OVf literal 64 zcmZQz_+KwkZd{b(xzr$8Vt)9~FcG&(S0mH=PSSSUOy%@rw01~_*{{(%6~=1ktlM9m UUAL-`H8ddewa5P=nWU0f0O?>C+W-In diff --git a/test/gfx/full_aco.png b/test/gfx/full_aco.png index de5a5849a134e1a9f529236f19e0b8df6d26d8ea..a7b2c25557ab7b475098bb3ba6191f878dad6e17 100644 GIT binary patch delta 532 zcmV+v0_**s2do5;BYy$&Nkl)fBFDQMijfh0-5e&x9XK4;B+bK_NzT{eNO?|-gp;J&a64!0_xI#~os z@CGPkwb=&Nh__B7o-i6C_Bnaoxds$&YfpGQ22?~;#8gC7#3c%lww4^m)jB~bkUs)?1pcno+ODRe#e2&PIcz*;r2IwVvR zd&0XS6ubd%BY%ZjBaD(dCe<;lMu}hdKrjYWgcuzPrxA6Gs$*Imqkq-||JFeEQqR6) zaAXmvCR7n?-^_#TYy+_VTL1jMg+dir9j(0?aPm;@fa~!Z;0LM*sEASc)Aky$M)*Da z!K@K0xKSJhT#v^9KfoGMqky{TY=llr%Ye20!TJWq0Do%=wZgk16ubeiiPS};hP|$) zH4*Zn%i0sZbX)-88?YAyUm*A@$Dzs_y6gqUk%AYT9WCt8XOC&`Rn|Ms<1yeF@veA| z07|GGE%==OXNB9t!ZXNy@fh$T;0wx delta 906 zcmV;519kkY1fK_xBYy*CNklJ3AOkK}W2at++{+@3t36nFIsvu{sM49UNUag0GyC_ z_2)A8b&;23pMjvtFOHr<0B1ICCTv#os~ZS;*|=;!m&*YF(loW6OEj-Pom%7l8JTXC z0}g~_IFJw2%YOiF$Om$R-QN@dJ|o(`8-*@>#F@97P5}6AJdXDOE~Af_!Gh~t9}p9_ z?*paq82~VpZ5?QHg@j)^S`d+K(b%xj8(lm8yK=PsKV(h}28RIvpw#IB0Fv78s|Sp~ zd5!|g)_B33H}eeSUYk$p`9Q((^0>`RS(!5~txC+awSOILyJ#}6FVnVXv~6D|ug+|r zksPB?C9%%qo-gwZ-06?|WzvQGx=BQ8MxT6}@qQb?$rpsY;{4pyGKCuVbD6-5^W0jf z8#3&?jX$rR?{*mQ+1R>G$3A`GeQZaiFO%t4 z4V&@Wg8OHlfji%WdbJ7wDAve;uOCFZg9bpkk^|U&q#HG7l&-BdGJ&=zl_5$j|3QyxFW+?-BB|MPzjLCvCp= zi2U9le|tV4n|DPWo3CF;Or}JaOl&@==Z!8A6GC2k9<=cj6QQLqM`XlBepq7dm3an^ z)u=LDpfDX$-$eHSfZ29)xf(#DW8%2Uyz0On9=J}uv1%i?YMlqHmE=>ZnZ&%JpL910 zW`CZ6i&{uszit6$TO#K6s;Xho;Qh}d8@scb$nMnKDpmJJ!;X!-+k3mn9~r9MS|0HE zzyyrz?wzIdk0pCrpN(r=47m40uFbpmQ$Eps)$K6g^MT%$2>R|YKbBnYvvG;fNB(Ey gV#MbonP=c1sdVwa20G`v00000NkvXXt^-0~f&i<*9RL6T diff --git a/test/gfx/full_act.out.pal b/test/gfx/full_act.out.pal index 820ff240b205aca691f9695ec6f9e47fe58a6006..45edb6b8d952d69c0d386c071774c551866c388a 100644 GIT binary patch literal 64 zcmZQz_+KwkZk(6ndDNg;Vt)9~FcG&(S0mH=PSSSUOy%@r^ma&^+ON?&6~=1ktean* UUAL-`Ei@qWwa5QFnWU0P0Ps*3(*OVf literal 64 zcmZQz_+KwkZd{b(xzr$8Vt)9~FcG&(S0mH=PSSSUOy%@rw01~_*{{(%6~=1ktlM9m UUAL-`H8ddewa5P=nWU0f0O?>C+W-In diff --git a/test/gfx/full_act.png b/test/gfx/full_act.png index de5a5849a134e1a9f529236f19e0b8df6d26d8ea..a7b2c25557ab7b475098bb3ba6191f878dad6e17 100644 GIT binary patch delta 532 zcmV+v0_**s2do5;BYy$&Nkl)fBFDQMijfh0-5e&x9XK4;B+bK_NzT{eNO?|-gp;J&a64!0_xI#~os z@CGPkwb=&Nh__B7o-i6C_Bnaoxds$&YfpGQ22?~;#8gC7#3c%lww4^m)jB~bkUs)?1pcno+ODRe#e2&PIcz*;r2IwVvR zd&0XS6ubd%BY%ZjBaD(dCe<;lMu}hdKrjYWgcuzPrxA6Gs$*Imqkq-||JFeEQqR6) zaAXmvCR7n?-^_#TYy+_VTL1jMg+dir9j(0?aPm;@fa~!Z;0LM*sEASc)Aky$M)*Da z!K@K0xKSJhT#v^9KfoGMqky{TY=llr%Ye20!TJWq0Do%=wZgk16ubeiiPS};hP|$) zH4*Zn%i0sZbX)-88?YAyUm*A@$Dzs_y6gqUk%AYT9WCt8XOC&`Rn|Ms<1yeF@veA| z07|GGE%==OXNB9t!ZXNy@fh$T;0wx delta 906 zcmV;519kkY1fK_xBYy*CNklJ3AOkK}W2at++{+@3t36nFIsvu{sM49UNUag0GyC_ z_2)A8b&;23pMjvtFOHr<0B1ICCTv#os~ZS;*|=;!m&*YF(loW6OEj-Pom%7l8JTXC z0}g~_IFJw2%YOiF$Om$R-QN@dJ|o(`8-*@>#F@97P5}6AJdXDOE~Af_!Gh~t9}p9_ z?*paq82~VpZ5?QHg@j)^S`d+K(b%xj8(lm8yK=PsKV(h}28RIvpw#IB0Fv78s|Sp~ zd5!|g)_B33H}eeSUYk$p`9Q((^0>`RS(!5~txC+awSOILyJ#}6FVnVXv~6D|ug+|r zksPB?C9%%qo-gwZ-06?|WzvQGx=BQ8MxT6}@qQb?$rpsY;{4pyGKCuVbD6-5^W0jf z8#3&?jX$rR?{*mQ+1R>G$3A`GeQZaiFO%t4 z4V&@Wg8OHlfji%WdbJ7wDAve;uOCFZg9bpkk^|U&q#HG7l&-BdGJ&=zl_5$j|3QyxFW+?-BB|MPzjLCvCp= zi2U9le|tV4n|DPWo3CF;Or}JaOl&@==Z!8A6GC2k9<=cj6QQLqM`XlBepq7dm3an^ z)u=LDpfDX$-$eHSfZ29)xf(#DW8%2Uyz0On9=J}uv1%i?YMlqHmE=>ZnZ&%JpL910 zW`CZ6i&{uszit6$TO#K6s;Xho;Qh}d8@scb$nMnKDpmJJ!;X!-+k3mn9~r9MS|0HE zzyyrz?wzIdk0pCrpN(r=47m40uFbpmQ$Eps)$K6g^MT%$2>R|YKbBnYvvG;fNB(Ey gV#MbonP=c1sdVwa20G`v00000NkvXXt^-0~f&i<*9RL6T diff --git a/test/gfx/full_gpl.out.pal b/test/gfx/full_gpl.out.pal index 820ff240b205aca691f9695ec6f9e47fe58a6006..45edb6b8d952d69c0d386c071774c551866c388a 100644 GIT binary patch literal 64 zcmZQz_+KwkZk(6ndDNg;Vt)9~FcG&(S0mH=PSSSUOy%@r^ma&^+ON?&6~=1ktean* UUAL-`Ei@qWwa5QFnWU0P0Ps*3(*OVf literal 64 zcmZQz_+KwkZd{b(xzr$8Vt)9~FcG&(S0mH=PSSSUOy%@rw01~_*{{(%6~=1ktlM9m UUAL-`H8ddewa5P=nWU0f0O?>C+W-In diff --git a/test/gfx/full_gpl.png b/test/gfx/full_gpl.png index de5a5849a134e1a9f529236f19e0b8df6d26d8ea..a7b2c25557ab7b475098bb3ba6191f878dad6e17 100644 GIT binary patch delta 532 zcmV+v0_**s2do5;BYy$&Nkl)fBFDQMijfh0-5e&x9XK4;B+bK_NzT{eNO?|-gp;J&a64!0_xI#~os z@CGPkwb=&Nh__B7o-i6C_Bnaoxds$&YfpGQ22?~;#8gC7#3c%lww4^m)jB~bkUs)?1pcno+ODRe#e2&PIcz*;r2IwVvR zd&0XS6ubd%BY%ZjBaD(dCe<;lMu}hdKrjYWgcuzPrxA6Gs$*Imqkq-||JFeEQqR6) zaAXmvCR7n?-^_#TYy+_VTL1jMg+dir9j(0?aPm;@fa~!Z;0LM*sEASc)Aky$M)*Da z!K@K0xKSJhT#v^9KfoGMqky{TY=llr%Ye20!TJWq0Do%=wZgk16ubeiiPS};hP|$) zH4*Zn%i0sZbX)-88?YAyUm*A@$Dzs_y6gqUk%AYT9WCt8XOC&`Rn|Ms<1yeF@veA| z07|GGE%==OXNB9t!ZXNy@fh$T;0wx delta 906 zcmV;519kkY1fK_xBYy*CNklJ3AOkK}W2at++{+@3t36nFIsvu{sM49UNUag0GyC_ z_2)A8b&;23pMjvtFOHr<0B1ICCTv#os~ZS;*|=;!m&*YF(loW6OEj-Pom%7l8JTXC z0}g~_IFJw2%YOiF$Om$R-QN@dJ|o(`8-*@>#F@97P5}6AJdXDOE~Af_!Gh~t9}p9_ z?*paq82~VpZ5?QHg@j)^S`d+K(b%xj8(lm8yK=PsKV(h}28RIvpw#IB0Fv78s|Sp~ zd5!|g)_B33H}eeSUYk$p`9Q((^0>`RS(!5~txC+awSOILyJ#}6FVnVXv~6D|ug+|r zksPB?C9%%qo-gwZ-06?|WzvQGx=BQ8MxT6}@qQb?$rpsY;{4pyGKCuVbD6-5^W0jf z8#3&?jX$rR?{*mQ+1R>G$3A`GeQZaiFO%t4 z4V&@Wg8OHlfji%WdbJ7wDAve;uOCFZg9bpkk^|U&q#HG7l&-BdGJ&=zl_5$j|3QyxFW+?-BB|MPzjLCvCp= zi2U9le|tV4n|DPWo3CF;Or}JaOl&@==Z!8A6GC2k9<=cj6QQLqM`XlBepq7dm3an^ z)u=LDpfDX$-$eHSfZ29)xf(#DW8%2Uyz0On9=J}uv1%i?YMlqHmE=>ZnZ&%JpL910 zW`CZ6i&{uszit6$TO#K6s;Xho;Qh}d8@scb$nMnKDpmJJ!;X!-+k3mn9~r9MS|0HE zzyyrz?wzIdk0pCrpN(r=47m40uFbpmQ$Eps)$K6g^MT%$2>R|YKbBnYvvG;fNB(Ey gV#MbonP=c1sdVwa20G`v00000NkvXXt^-0~f&i<*9RL6T diff --git a/test/gfx/full_psp.out.pal b/test/gfx/full_psp.out.pal index 820ff240b205aca691f9695ec6f9e47fe58a6006..45edb6b8d952d69c0d386c071774c551866c388a 100644 GIT binary patch literal 64 zcmZQz_+KwkZk(6ndDNg;Vt)9~FcG&(S0mH=PSSSUOy%@r^ma&^+ON?&6~=1ktean* UUAL-`Ei@qWwa5QFnWU0P0Ps*3(*OVf literal 64 zcmZQz_+KwkZd{b(xzr$8Vt)9~FcG&(S0mH=PSSSUOy%@rw01~_*{{(%6~=1ktlM9m UUAL-`H8ddewa5P=nWU0f0O?>C+W-In diff --git a/test/gfx/full_psp.png b/test/gfx/full_psp.png index de5a5849a134e1a9f529236f19e0b8df6d26d8ea..a7b2c25557ab7b475098bb3ba6191f878dad6e17 100644 GIT binary patch delta 532 zcmV+v0_**s2do5;BYy$&Nkl)fBFDQMijfh0-5e&x9XK4;B+bK_NzT{eNO?|-gp;J&a64!0_xI#~os z@CGPkwb=&Nh__B7o-i6C_Bnaoxds$&YfpGQ22?~;#8gC7#3c%lww4^m)jB~bkUs)?1pcno+ODRe#e2&PIcz*;r2IwVvR zd&0XS6ubd%BY%ZjBaD(dCe<;lMu}hdKrjYWgcuzPrxA6Gs$*Imqkq-||JFeEQqR6) zaAXmvCR7n?-^_#TYy+_VTL1jMg+dir9j(0?aPm;@fa~!Z;0LM*sEASc)Aky$M)*Da z!K@K0xKSJhT#v^9KfoGMqky{TY=llr%Ye20!TJWq0Do%=wZgk16ubeiiPS};hP|$) zH4*Zn%i0sZbX)-88?YAyUm*A@$Dzs_y6gqUk%AYT9WCt8XOC&`Rn|Ms<1yeF@veA| z07|GGE%==OXNB9t!ZXNy@fh$T;0wx delta 906 zcmV;519kkY1fK_xBYy*CNklJ3AOkK}W2at++{+@3t36nFIsvu{sM49UNUag0GyC_ z_2)A8b&;23pMjvtFOHr<0B1ICCTv#os~ZS;*|=;!m&*YF(loW6OEj-Pom%7l8JTXC z0}g~_IFJw2%YOiF$Om$R-QN@dJ|o(`8-*@>#F@97P5}6AJdXDOE~Af_!Gh~t9}p9_ z?*paq82~VpZ5?QHg@j)^S`d+K(b%xj8(lm8yK=PsKV(h}28RIvpw#IB0Fv78s|Sp~ zd5!|g)_B33H}eeSUYk$p`9Q((^0>`RS(!5~txC+awSOILyJ#}6FVnVXv~6D|ug+|r zksPB?C9%%qo-gwZ-06?|WzvQGx=BQ8MxT6}@qQb?$rpsY;{4pyGKCuVbD6-5^W0jf z8#3&?jX$rR?{*mQ+1R>G$3A`GeQZaiFO%t4 z4V&@Wg8OHlfji%WdbJ7wDAve;uOCFZg9bpkk^|U&q#HG7l&-BdGJ&=zl_5$j|3QyxFW+?-BB|MPzjLCvCp= zi2U9le|tV4n|DPWo3CF;Or}JaOl&@==Z!8A6GC2k9<=cj6QQLqM`XlBepq7dm3an^ z)u=LDpfDX$-$eHSfZ29)xf(#DW8%2Uyz0On9=J}uv1%i?YMlqHmE=>ZnZ&%JpL910 zW`CZ6i&{uszit6$TO#K6s;Xho;Qh}d8@scb$nMnKDpmJJ!;X!-+k3mn9~r9MS|0HE zzyyrz?wzIdk0pCrpN(r=47m40uFbpmQ$Eps)$K6g^MT%$2>R|YKbBnYvvG;fNB(Ey gV#MbonP=c1sdVwa20G`v00000NkvXXt^-0~f&i<*9RL6T diff --git a/test/gfx/interlaced.out.pal b/test/gfx/interlaced.out.pal index 8cdc1c73dc852c158cace3d0bf4a6e73a1b8e139..557777fc545058920fe0abe8545a794e1e47189c 100644 GIT binary patch delta 46 ucmZ>8ko{l(px&WwK@EgtVEA7j&%B>;iU^pTC@aa;YR16u+x~%Ys~G^y@Dcz3 delta 46 ucmZ>8ko{l(px&Xbp$0-SF#NBtXWq|PA_68S%1Uyzm@zQ?wtpbpVg>-kWD&jq diff --git a/test/gfx/randtilegen.cpp b/test/gfx/randtilegen.cpp index 089de824..e4965abc 100644 --- a/test/gfx/randtilegen.cpp +++ b/test/gfx/randtilegen.cpp @@ -144,7 +144,7 @@ static void generate_palettes(uint16_t palettes[/* 60 */][4]) { * Expand a 5-bit color component to 8 bits with minimal bias */ static uint8_t _5to8(uint8_t five) { - return five << 3 | five >> 2; + return (five * 255 + 15) / 31; } // Can't mark as `const`, as the array type is otherwise not compatible (augh)