Skip to content

Commit f430322

Browse files
committed
Improved radarcol and hue conversion.
1 parent d86a483 commit f430322

8 files changed

Lines changed: 1576 additions & 451 deletions

File tree

Ultima/Helpers/HueHelpers.cs

Lines changed: 52 additions & 38 deletions
Original file line numberDiff line numberDiff line change
@@ -15,63 +15,77 @@ namespace Ultima.Helpers
1515
{
1616
public static class HueHelpers
1717
{
18-
/// <summary>
19-
/// Converts RGB value to Hue color
20-
/// </summary>
21-
/// <param name="color"></param>
22-
/// <returns></returns>
23-
public static ushort ColorToHue(Color color)
18+
// Canonical 8-bit RGB -> 15-bit hue. Uses bit-shift (>>3) packing with the rule:
19+
// input all-zero -> 0; else any lane that collapses to 0 -> 1.
20+
public static ushort ColorToHue(Color color) => ColorToHueShift(color.R, color.G, color.B);
21+
22+
// Canonical 15-bit hue -> 32-bit ARGB, expanding 5-bit components via
23+
// (c<<3)|(c>>2) so 31 maps to 255 (not 248 as the previous *8 integer math did).
24+
public static Color HueToColor(ushort hue)
2425
{
25-
const double scale = 31.0 / 255;
26+
return Color.FromArgb(
27+
Expand5To8((hue & 0x7c00) >> 10),
28+
Expand5To8((hue & 0x03e0) >> 5),
29+
Expand5To8(hue & 0x001f));
30+
}
2631

27-
ushort origRed = color.R;
28-
var newRed = (ushort)(origRed * scale);
29-
if (newRed == 0 && origRed != 0)
30-
{
31-
newRed = 1;
32-
}
32+
public static int HueToColorR(ushort hue) => Expand5To8((hue & 0x7c00) >> 10);
33+
public static int HueToColorG(ushort hue) => Expand5To8((hue & 0x03e0) >> 5);
34+
public static int HueToColorB(ushort hue) => Expand5To8(hue & 0x001f);
3335

34-
ushort origGreen = color.G;
35-
var newGreen = (ushort)(origGreen * scale);
36-
if (newGreen == 0 && origGreen != 0)
36+
// Canonical RGB->555 packer for this format. Packs each channel via bit-shift:
37+
// result = ((r>>3) << 10) | ((g>>3) << 5) | (b>>3)
38+
// Clamp rule: if r|g|b == 0 the pixel is 0 (transparent); else if a lane
39+
// downscales to 0, force that lane to 1.
40+
public static ushort ColorToHueShift(int r8, int g8, int b8)
41+
{
42+
if ((r8 | g8 | b8) == 0)
3743
{
38-
newGreen = 1;
44+
return 0;
3945
}
4046

41-
ushort origBlue = color.B;
42-
var newBlue = (ushort)(origBlue * scale);
43-
if (newBlue == 0 && origBlue != 0)
47+
int r5 = r8 >> 3;
48+
int g5 = g8 >> 3;
49+
int b5 = b8 >> 3;
50+
if (r5 == 0 && g5 == 0 && b5 == 0)
4451
{
45-
newBlue = 1;
52+
return 1;
4653
}
4754

48-
return (ushort)((newRed << 10) | (newGreen << 5) | newBlue);
55+
return (ushort)((r5 << 10) | (g5 << 5) | b5);
4956
}
5057

51-
/// <summary>
52-
/// Converts Hue color to RGB color
53-
/// </summary>
54-
/// <param name="hue"></param>
55-
/// <returns></returns>
56-
public static Color HueToColor(ushort hue)
58+
// Rounding alternative: ((c*31 + 127) / 255). Same clamp rule as the shift version.
59+
public static ushort ColorToHueRounded(int r8, int g8, int b8)
5760
{
58-
const int scale = 255 / 31;
59-
return Color.FromArgb(((hue & 0x7c00) >> 10) * scale, ((hue & 0x3e0) >> 5) * scale, (hue & 0x1f) * scale);
60-
}
61+
if ((r8 | g8 | b8) == 0)
62+
{
63+
return 0;
64+
}
6165

62-
public static int HueToColorR(ushort hue)
63-
{
64-
return ((hue & 0x7c00) >> 10) * (255 / 31);
66+
int r5 = (r8 * 31 + 127) / 255;
67+
int g5 = (g8 * 31 + 127) / 255;
68+
int b5 = (b8 * 31 + 127) / 255;
69+
if (r5 == 0 && g5 == 0 && b5 == 0)
70+
{
71+
return 1;
72+
}
73+
74+
return (ushort)((r5 << 10) | (g5 << 5) | b5);
6575
}
6676

67-
public static int HueToColorG(ushort hue)
77+
public static void HueExtract5(ushort hue, out int r5, out int g5, out int b5)
6878
{
69-
return ((hue & 0x3e0) >> 5) * (255 / 31);
79+
r5 = (hue & 0x7c00) >> 10;
80+
g5 = (hue & 0x03e0) >> 5;
81+
b5 = hue & 0x001f;
7082
}
7183

72-
public static int HueToColorB(ushort hue)
84+
// Canonical 5-bit -> 8-bit expansion: replicate top 3 bits into the low ones.
85+
// Equivalent to round(c5 * 255 / 31). 0->0, 31->255, monotonic.
86+
public static int Expand5To8(int c5)
7387
{
74-
return (hue & 0x1f) * (255 / 31);
88+
return (c5 << 3) | (c5 >> 2);
7589
}
7690
}
7791
}

Ultima/Hues.cs

Lines changed: 9 additions & 49 deletions
Original file line numberDiff line numberDiff line change
@@ -149,54 +149,6 @@ public static Hue GetHue(int index)
149149
return List[0];
150150
}
151151

152-
/// <summary>
153-
/// Converts RGB value to Hue color
154-
/// </summary>
155-
/// <param name="color"></param>
156-
/// <returns></returns>
157-
public static ushort ColorToHue(Color color)
158-
{
159-
const double scale = 31.0 / 255;
160-
161-
ushort origRed = color.R;
162-
var newRed = (ushort)(origRed * scale);
163-
if (newRed == 0 && origRed != 0)
164-
{
165-
newRed = 1;
166-
}
167-
168-
ushort origGreen = color.G;
169-
var newGreen = (ushort)(origGreen * scale);
170-
if (newGreen == 0 && origGreen != 0)
171-
{
172-
newGreen = 1;
173-
}
174-
175-
ushort origBlue = color.B;
176-
var newBlue = (ushort)(origBlue * scale);
177-
if (newBlue == 0 && origBlue != 0)
178-
{
179-
newBlue = 1;
180-
}
181-
182-
return (ushort)((newRed << 10) | (newGreen << 5) | newBlue);
183-
}
184-
185-
public static int HueToColorR(ushort hue)
186-
{
187-
return ((hue & 0x7c00) >> 10) * (255 / 31);
188-
}
189-
190-
public static int HueToColorG(ushort hue)
191-
{
192-
return ((hue & 0x3e0) >> 5) * (255 / 31);
193-
}
194-
195-
public static int HueToColorB(ushort hue)
196-
{
197-
return (hue & 0x1f) * (255 / 31);
198-
}
199-
200152
public static unsafe void ApplyTo(Bitmap bmp, ushort[] colors, bool onlyHueGrayPixels)
201153
{
202154
BitmapData bd = bmp.LockBits(
@@ -334,7 +286,15 @@ public Hue(int index, HueDataMul mulStruct)
334286
Colors = new ushort[32];
335287
for (int i = 0; i < 32; ++i)
336288
{
337-
Colors[i] = mulStruct.colors[i];
289+
ushort c = mulStruct.colors[i];
290+
// Clamp c == 0 or any value with the high bit set to 1. The high bit is a
291+
// flag in this format, never part of a valid color value.
292+
if (c == 0 || c > 0x7fff)
293+
{
294+
c = 1;
295+
}
296+
297+
Colors[i] = c;
338298
}
339299

340300
TableStart = mulStruct.tableStart;

UoFiddler.Controls/Classes/Options.cs

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,12 @@ public static class Options
3232
/// </summary>
3333
public static bool ArtItemClip { get; set; } = true;
3434

35+
/// <summary>
36+
/// Strategy used by the RadarColor control to derive a 16-bit color from a tile graphic.
37+
/// Runtime-only (not persisted across sessions yet).
38+
/// </summary>
39+
public static RadarAveragingStrategy RadarColorStrategy { get; set; } = RadarAveragingStrategy.Mean5BankersRound;
40+
3541
/// <summary>
3642
/// Offsets the sound ids in Sound tab by 1 (POL specific setting)
3743
/// </summary>

0 commit comments

Comments
 (0)