Skip to content

Commit 8f0f946

Browse files
committed
More accurate conversion from uint to ushort and byte
1 parent aacbfbd commit 8f0f946

File tree

2 files changed

+15
-12
lines changed

2 files changed

+15
-12
lines changed

AssetRipper.TextureDecoder.ColorGenerator/NumericConversionGenerator.cs

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -229,6 +229,13 @@ private static void WriteConvertMethod(IndentedTextWriter writer, CSharpPrimitiv
229229
writer.WriteLine("byte converted = unchecked((byte)x);");
230230
writer.WriteLine("return Unsafe.As<byte, TTo>(ref converted);");
231231
}
232+
else if (from.Size < sizeof(double) && to.Size < sizeof(double))
233+
{
234+
writer.WriteLine($"double interpolated = (double)value / (double){from.MaxValue};");
235+
writer.WriteLine($"double exact = interpolated * (double){to.MaxValue};");
236+
writer.WriteLine($"{to.LangName} converted = ({to.LangName})double.Round(exact, MidpointRounding.AwayFromZero);");
237+
writer.WriteLine($"return Unsafe.As<{to.LangName}, TTo>(ref converted);");
238+
}
232239
else
233240
{
234241
writer.WriteComment($"There are more accurate ways to map {from.TypeName} onto {to.TypeName}, but this is the simplest.");

AssetRipper.TextureDecoder/Rgb/NumericConversion.g.cs

Lines changed: 8 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -383,12 +383,10 @@ private static TTo ConvertUInt32<TTo>(uint value) where TTo : unmanaged
383383
else if (typeof(TTo) == typeof(byte))
384384
{
385385
// See https://github.com/AssetRipper/TextureDecoder/issues/19
386-
// There are more accurate ways to map UInt32 onto Byte, but this is the simplest.
387-
unchecked
388-
{
389-
byte converted = (byte)((uint)value >> 24);
390-
return Unsafe.As<byte, TTo>(ref converted);
391-
}
386+
double interpolated = (double)value / (double)uint.MaxValue;
387+
double exact = interpolated * (double)byte.MaxValue;
388+
byte converted = (byte)double.Round(exact, MidpointRounding.AwayFromZero);
389+
return Unsafe.As<byte, TTo>(ref converted);
392390
}
393391
else if (typeof(TTo) == typeof(short))
394392
{
@@ -398,12 +396,10 @@ private static TTo ConvertUInt32<TTo>(uint value) where TTo : unmanaged
398396
else if (typeof(TTo) == typeof(ushort))
399397
{
400398
// See https://github.com/AssetRipper/TextureDecoder/issues/19
401-
// There are more accurate ways to map UInt32 onto UInt16, but this is the simplest.
402-
unchecked
403-
{
404-
ushort converted = (ushort)((uint)value >> 16);
405-
return Unsafe.As<ushort, TTo>(ref converted);
406-
}
399+
double interpolated = (double)value / (double)uint.MaxValue;
400+
double exact = interpolated * (double)ushort.MaxValue;
401+
ushort converted = (ushort)double.Round(exact, MidpointRounding.AwayFromZero);
402+
return Unsafe.As<ushort, TTo>(ref converted);
407403
}
408404
else if (typeof(TTo) == typeof(int))
409405
{

0 commit comments

Comments
 (0)