diff --git a/CHANGELOG.md b/CHANGELOG.md
index b0d138b..52611e2 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -2,6 +2,27 @@
This library uses [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
+## 0.8.0
+
+### Added
+
+- Added utility methods to pack `Rgba` data into an `int` and vice versa:
+ - `ToRgbaInt`
+ - `ToArgbInt`
+ - `FromRgbaInt`
+ - `FromArgbInt`
+
+### Changed
+
+- Renamed `Color` to `Rgba` to avoid conflicts with System.Drawing.
+- Renamed `ReadColor` in `BinaryReaderExtensions` to `ReadRgba`.
+- Renamed `RandomColor` in `RandomExtensions` to `RandomRgba`.
+- The `A` parameter in the `Rgba` constructor is now optional.
+
+### Removed
+
+- Removed `ReadableColorForBrightness` from `Rgba`.
+
## 0.7.0
### Added
diff --git a/src/Detach.Tests/Tests/Numerics/RgbaTests.cs b/src/Detach.Tests/Tests/Numerics/RgbaTests.cs
new file mode 100644
index 0000000..d3273d0
--- /dev/null
+++ b/src/Detach.Tests/Tests/Numerics/RgbaTests.cs
@@ -0,0 +1,30 @@
+using Detach.Numerics;
+using Microsoft.VisualStudio.TestTools.UnitTesting;
+using System.Numerics;
+
+namespace Detach.Tests.Tests.Numerics;
+
+[TestClass]
+public class RgbaTests
+{
+ [DataTestMethod]
+ [DataRow(0, 0, 0, 0)]
+ [DataRow(1, 2, 3, 4)]
+ [DataRow(5, 6, 7, 8)]
+ [DataRow(255, 6, 255, 8)]
+ [DataRow(255, 255, 255, 255)]
+ public void RgbaConversions(int r, int g, int b, int a)
+ {
+ Rgba expectedRgba = new((byte)r, (byte)g, (byte)b, (byte)a);
+ Rgba expectedRgb = expectedRgba with { A = byte.MaxValue };
+
+ Assert.AreEqual(expectedRgba, Rgba.FromVector4(new Vector4(r / 255f, g / 255f, b / 255f, a / 255f)));
+ Assert.AreEqual(expectedRgb, Rgba.FromVector3(new Vector3(r / 255f, g / 255f, b / 255f)));
+
+ Assert.AreEqual(expectedRgba, Rgba.FromRgbaInt(expectedRgba.ToRgbaInt()));
+ Assert.AreEqual(expectedRgb, Rgba.FromRgbaInt(expectedRgb.ToRgbaInt()));
+
+ Assert.AreEqual(expectedRgba, Rgba.FromArgbInt(expectedRgba.ToArgbInt()));
+ Assert.AreEqual(expectedRgb, Rgba.FromArgbInt(expectedRgb.ToArgbInt()));
+ }
+}
diff --git a/src/Detach/Detach.csproj b/src/Detach/Detach.csproj
index 7fecbcd..afe9130 100644
--- a/src/Detach/Detach.csproj
+++ b/src/Detach/Detach.csproj
@@ -14,7 +14,7 @@
Copyright © Noah Stolk
git
https://github.com/NoahStolk/Detach
- 0.7.0
+ 0.8.0
diff --git a/src/Detach/Extensions/BinaryReaderExtensions.cs b/src/Detach/Extensions/BinaryReaderExtensions.cs
index 8fe959f..125661d 100644
--- a/src/Detach/Extensions/BinaryReaderExtensions.cs
+++ b/src/Detach/Extensions/BinaryReaderExtensions.cs
@@ -55,9 +55,9 @@ public static Matrix4x4 ReadMatrix4x4(this BinaryReader br)
br.ReadSingle(), br.ReadSingle(), br.ReadSingle(), br.ReadSingle());
}
- public static Color ReadColor(this BinaryReader br)
+ public static Rgba ReadRgba(this BinaryReader br)
{
- return new Color(br.ReadByte(), br.ReadByte(), br.ReadByte(), br.ReadByte());
+ return new Rgba(br.ReadByte(), br.ReadByte(), br.ReadByte(), br.ReadByte());
}
public static List ReadLengthPrefixedList(this BinaryReader br, Func reader)
diff --git a/src/Detach/Extensions/BinaryWriterExtensions.cs b/src/Detach/Extensions/BinaryWriterExtensions.cs
index fe0ab89..f1ccc51 100644
--- a/src/Detach/Extensions/BinaryWriterExtensions.cs
+++ b/src/Detach/Extensions/BinaryWriterExtensions.cs
@@ -73,12 +73,12 @@ public static void Write(this BinaryWriter bw, Matrix4x4 matrix)
bw.Write(matrix.M44);
}
- public static void Write(this BinaryWriter bw, Color color)
+ public static void Write(this BinaryWriter bw, Rgba rgba)
{
- bw.Write(color.R);
- bw.Write(color.G);
- bw.Write(color.B);
- bw.Write(color.A);
+ bw.Write(rgba.R);
+ bw.Write(rgba.G);
+ bw.Write(rgba.B);
+ bw.Write(rgba.A);
}
public static void WriteLengthPrefixedList(this BinaryWriter bw, List list, Action writer)
diff --git a/src/Detach/Extensions/RandomExtensions.cs b/src/Detach/Extensions/RandomExtensions.cs
index 3b84d95..a55a1f6 100644
--- a/src/Detach/Extensions/RandomExtensions.cs
+++ b/src/Detach/Extensions/RandomExtensions.cs
@@ -486,33 +486,33 @@ public static Vector4 RandomVector4(this Random random, Vector4 minValue, Vector
}
///
- /// Returns a random with values that are greater than or equal to the corresponding min parameters, and less than the corresponding max parameters.
+ /// Returns a random with values that are greater than or equal to the corresponding min parameters, and less than the corresponding max parameters.
///
/// The instance.
- /// The minimum X value for the .
- /// The maximum X value for the .
- /// The minimum Y value for the .
- /// The maximum Y value for the .
- /// The minimum Z value for the .
- /// The maximum Z value for the .
- /// The minimum W value for the .
- /// The maximum W value for the .
- /// The random .
- public static Color RandomColor(this Random random, byte minValueX, byte maxValueX, byte minValueY, byte maxValueY, byte minValueZ, byte maxValueZ, byte minValueW, byte maxValueW)
+ /// The minimum X value for the .
+ /// The maximum X value for the .
+ /// The minimum Y value for the .
+ /// The maximum Y value for the .
+ /// The minimum Z value for the .
+ /// The maximum Z value for the .
+ /// The minimum W value for the .
+ /// The maximum W value for the .
+ /// The random .
+ public static Rgba RandomRgba(this Random random, byte minValueX, byte maxValueX, byte minValueY, byte maxValueY, byte minValueZ, byte maxValueZ, byte minValueW, byte maxValueW)
{
- return new Color(random.RandomByte(minValueX, maxValueX), random.RandomByte(minValueY, maxValueY), random.RandomByte(minValueZ, maxValueZ), random.RandomByte(minValueW, maxValueW));
+ return new Rgba(random.RandomByte(minValueX, maxValueX), random.RandomByte(minValueY, maxValueY), random.RandomByte(minValueZ, maxValueZ), random.RandomByte(minValueW, maxValueW));
}
///
- /// Returns a random with values that are all greater than or equal to , and less than .
+ /// Returns a random with values that are all greater than or equal to , and less than .
///
/// The instance.
/// The minimum value.
/// The maximum value.
- /// The random .
- public static Color RandomColor(this Random random, Color minValue, Color maxValue)
+ /// The random .
+ public static Rgba RandomRgba(this Random random, Rgba minValue, Rgba maxValue)
{
- return random.RandomColor(minValue.R, maxValue.R, minValue.G, maxValue.G, minValue.B, maxValue.B, minValue.A, maxValue.A);
+ return random.RandomRgba(minValue.R, maxValue.R, minValue.G, maxValue.G, minValue.B, maxValue.B, minValue.A, maxValue.A);
}
///
diff --git a/src/Detach/Inline.cs b/src/Detach/Inline.cs
index b6b0e8e..9ea843d 100644
--- a/src/Detach/Inline.cs
+++ b/src/Detach/Inline.cs
@@ -70,7 +70,7 @@ public static ReadOnlySpan Span(Quaternion value, ReadOnlySpan forma
return _buffer.AsSpan(0, charsWritten);
}
- public static ReadOnlySpan Span(Color value, ReadOnlySpan format = default, IFormatProvider? provider = default)
+ public static ReadOnlySpan Span(Rgba value, ReadOnlySpan format = default, IFormatProvider? provider = default)
{
int charsWritten = 0;
TryWrite(_buffer, ref charsWritten, value.R, format, provider);
diff --git a/src/Detach/Numerics/Color.cs b/src/Detach/Numerics/Color.cs
deleted file mode 100644
index 338dec0..0000000
--- a/src/Detach/Numerics/Color.cs
+++ /dev/null
@@ -1,179 +0,0 @@
-using Detach.Utils;
-using System.Numerics;
-using System.Runtime.CompilerServices;
-
-namespace Detach.Numerics;
-
-public readonly record struct Color(byte R, byte G, byte B, byte A)
-{
- public static Color Invisible { get; } = new(byte.MinValue, byte.MinValue, byte.MinValue, byte.MinValue);
-
- public static Color White { get; } = new(byte.MaxValue, byte.MaxValue, byte.MaxValue, byte.MaxValue);
- public static Color Black { get; } = new(byte.MinValue, byte.MinValue, byte.MinValue, byte.MaxValue);
-
- public static Color HalfTransparentWhite { get; } = new(byte.MaxValue, byte.MaxValue, byte.MaxValue, byte.MaxValue / 2);
- public static Color HalfTransparentBlack { get; } = new(byte.MinValue, byte.MinValue, byte.MinValue, byte.MaxValue / 2);
-
- public static Color Red { get; } = new(byte.MaxValue, byte.MinValue, byte.MinValue, byte.MaxValue);
- public static Color Green { get; } = new(byte.MinValue, byte.MaxValue, byte.MinValue, byte.MaxValue);
- public static Color Blue { get; } = new(byte.MinValue, byte.MinValue, byte.MaxValue, byte.MaxValue);
-
- public static Color Yellow { get; } = new(byte.MaxValue, byte.MaxValue, byte.MinValue, byte.MaxValue);
- public static Color Aqua { get; } = new(byte.MinValue, byte.MaxValue, byte.MaxValue, byte.MaxValue);
- public static Color Purple { get; } = new(byte.MaxValue, byte.MinValue, byte.MaxValue, byte.MaxValue);
-
- public static Color Orange { get; } = new(byte.MaxValue, byte.MaxValue / 2, byte.MinValue, byte.MaxValue);
-
- public static implicit operator Vector3(Color color)
- {
- return new Vector3(color.R / (float)byte.MaxValue, color.G / (float)byte.MaxValue, color.B / (float)byte.MaxValue);
- }
-
- public static implicit operator Vector4(Color color)
- {
- return new Vector4(color.R / (float)byte.MaxValue, color.G / (float)byte.MaxValue, color.B / (float)byte.MaxValue, color.A / (float)byte.MaxValue);
- }
-
- [MethodImpl(MethodImplOptions.AggressiveInlining)]
- public static Color operator +(Color left, Color right)
- {
- return new Color((byte)(left.R + right.R), (byte)(left.G + right.G), (byte)(left.B + right.B), (byte)(left.A + right.A));
- }
-
- [MethodImpl(MethodImplOptions.AggressiveInlining)]
- public static Color operator -(Color left, Color right)
- {
- return new Color((byte)(left.R - right.R), (byte)(left.G - right.G), (byte)(left.B - right.B), (byte)(left.A - right.A));
- }
-
- [MethodImpl(MethodImplOptions.AggressiveInlining)]
- public static Color operator *(Color left, Color right)
- {
- return new Color((byte)(left.R * right.R), (byte)(left.G * right.G), (byte)(left.B * right.B), (byte)(left.A * right.A));
- }
-
- [MethodImpl(MethodImplOptions.AggressiveInlining)]
- public static Color operator /(Color left, Color right)
- {
- return new Color((byte)(left.R / right.R), (byte)(left.G / right.G), (byte)(left.B / right.B), (byte)(left.A / right.A));
- }
-
- public Color ReadableColorForBrightness()
- {
- return GetPerceivedBrightness() < 140 ? White : Black;
- }
-
- public int GetPerceivedBrightness()
- {
- return (int)Math.Sqrt(R * R * 0.299 + G * G * 0.587 + B * B * 0.114);
- }
-
- public Color Intensify(byte component)
- {
- byte r = (byte)Math.Min(byte.MaxValue, R + component);
- byte g = (byte)Math.Min(byte.MaxValue, G + component);
- byte b = (byte)Math.Min(byte.MaxValue, B + component);
- byte a = (byte)Math.Min(byte.MaxValue, A + component);
- return new Color(r, g, b, a);
- }
-
- public Color Desaturate(float f)
- {
- float r = R / (float)byte.MaxValue;
- float g = G / (float)byte.MaxValue;
- float b = B / (float)byte.MaxValue;
-
- float l = 0.3f * r + 0.6f * g + 0.1f * b;
- float newR = r + f * (l - r);
- float newG = g + f * (l - g);
- float newB = b + f * (l - b);
-
- return new Color((byte)(newR * byte.MaxValue), (byte)(newG * byte.MaxValue), (byte)(newB * byte.MaxValue), A);
- }
-
- public Color Darken(float amount)
- {
- return new Color((byte)(R * (1 - amount)), (byte)(G * (1 - amount)), (byte)(B * (1 - amount)), A);
- }
-
- public int GetHue()
- {
- byte min = Math.Min(Math.Min(R, G), B);
- byte max = Math.Max(Math.Max(R, G), B);
-
- if (min == max)
- return 0;
-
- float hue;
- if (max == R)
- hue = (G - B) / (float)(max - min);
- else if (max == G)
- hue = 2f + (B - R) / (float)(max - min);
- else
- hue = 4f + (R - G) / (float)(max - min);
-
- hue *= 60;
- if (hue < 0)
- hue += 360;
-
- return (int)Math.Round(hue);
- }
-
- public static Color Lerp(Color value1, Color value2, float amount)
- {
- float r = MathUtils.Lerp(value1.R, value2.R, amount);
- float g = MathUtils.Lerp(value1.G, value2.G, amount);
- float b = MathUtils.Lerp(value1.B, value2.B, amount);
- float a = MathUtils.Lerp(value1.A, value2.A, amount);
- return new Color((byte)r, (byte)g, (byte)b, (byte)a);
- }
-
- public static Color Invert(Color color)
- {
- return new Color((byte)(byte.MaxValue - color.R), (byte)(byte.MaxValue - color.G), (byte)(byte.MaxValue - color.B), color.A);
- }
-
- public static Color Gray(float value)
- {
- if (value is < 0 or > 1)
- throw new ArgumentOutOfRangeException(nameof(value));
-
- byte component = (byte)(value * byte.MaxValue);
- return new Color(component, component, component, byte.MaxValue);
- }
-
- public static Color FromHsv(float hue, float saturation, float value)
- {
- saturation = Math.Clamp(saturation, 0, 1);
- value = Math.Clamp(value, 0, 1);
-
- int hi = (int)MathF.Floor(hue / 60) % 6;
- float f = hue / 60 - MathF.Floor(hue / 60);
-
- value *= byte.MaxValue;
- byte v = (byte)value;
- byte p = (byte)(value * (1 - saturation));
- byte q = (byte)(value * (1 - f * saturation));
- byte t = (byte)(value * (1 - (1 - f) * saturation));
-
- return hi switch
- {
- 0 => new Color(v, t, p, byte.MaxValue),
- 1 => new Color(q, v, p, byte.MaxValue),
- 2 => new Color(p, v, t, byte.MaxValue),
- 3 => new Color(p, q, v, byte.MaxValue),
- 4 => new Color(t, p, v, byte.MaxValue),
- _ => new Color(v, p, q, byte.MaxValue),
- };
- }
-
- public static Color FromVector3(Vector3 vector)
- {
- return new Color((byte)(vector.X * byte.MaxValue), (byte)(vector.Y * byte.MaxValue), (byte)(vector.Z * byte.MaxValue), byte.MaxValue);
- }
-
- public static Color FromVector4(Vector4 vector)
- {
- return new Color((byte)(vector.X * byte.MaxValue), (byte)(vector.Y * byte.MaxValue), (byte)(vector.Z * byte.MaxValue), (byte)(vector.W * byte.MaxValue));
- }
-}
diff --git a/src/Detach/Numerics/Rgba.cs b/src/Detach/Numerics/Rgba.cs
new file mode 100644
index 0000000..4294827
--- /dev/null
+++ b/src/Detach/Numerics/Rgba.cs
@@ -0,0 +1,194 @@
+using Detach.Utils;
+using System.Numerics;
+using System.Runtime.CompilerServices;
+
+namespace Detach.Numerics;
+
+public readonly record struct Rgba(byte R, byte G, byte B, byte A = byte.MaxValue)
+{
+ public static Rgba Invisible => default;
+
+ public static Rgba White => new(byte.MaxValue, byte.MaxValue, byte.MaxValue);
+ public static Rgba Black => new(byte.MinValue, byte.MinValue, byte.MinValue);
+
+ public static Rgba HalfTransparentWhite => new(byte.MaxValue, byte.MaxValue, byte.MaxValue, byte.MaxValue / 2);
+ public static Rgba HalfTransparentBlack => new(byte.MinValue, byte.MinValue, byte.MinValue, byte.MaxValue / 2);
+
+ public static Rgba Red => new(byte.MaxValue, byte.MinValue, byte.MinValue);
+ public static Rgba Green => new(byte.MinValue, byte.MaxValue, byte.MinValue);
+ public static Rgba Blue => new(byte.MinValue, byte.MinValue, byte.MaxValue);
+
+ public static Rgba Yellow => new(byte.MaxValue, byte.MaxValue, byte.MinValue);
+ public static Rgba Aqua => new(byte.MinValue, byte.MaxValue, byte.MaxValue);
+ public static Rgba Purple => new(byte.MaxValue, byte.MinValue, byte.MaxValue);
+
+ public static Rgba Orange => new(byte.MaxValue, byte.MaxValue / 2, byte.MinValue);
+
+ public static implicit operator Vector3(Rgba rgba)
+ {
+ return new Vector3(rgba.R / (float)byte.MaxValue, rgba.G / (float)byte.MaxValue, rgba.B / (float)byte.MaxValue);
+ }
+
+ public static implicit operator Vector4(Rgba rgba)
+ {
+ return new Vector4(rgba.R / (float)byte.MaxValue, rgba.G / (float)byte.MaxValue, rgba.B / (float)byte.MaxValue, rgba.A / (float)byte.MaxValue);
+ }
+
+ [MethodImpl(MethodImplOptions.AggressiveInlining)]
+ public static Rgba operator +(Rgba left, Rgba right)
+ {
+ return new Rgba((byte)(left.R + right.R), (byte)(left.G + right.G), (byte)(left.B + right.B), (byte)(left.A + right.A));
+ }
+
+ [MethodImpl(MethodImplOptions.AggressiveInlining)]
+ public static Rgba operator -(Rgba left, Rgba right)
+ {
+ return new Rgba((byte)(left.R - right.R), (byte)(left.G - right.G), (byte)(left.B - right.B), (byte)(left.A - right.A));
+ }
+
+ [MethodImpl(MethodImplOptions.AggressiveInlining)]
+ public static Rgba operator *(Rgba left, Rgba right)
+ {
+ return new Rgba((byte)(left.R * right.R), (byte)(left.G * right.G), (byte)(left.B * right.B), (byte)(left.A * right.A));
+ }
+
+ [MethodImpl(MethodImplOptions.AggressiveInlining)]
+ public static Rgba operator /(Rgba left, Rgba right)
+ {
+ return new Rgba((byte)(left.R / right.R), (byte)(left.G / right.G), (byte)(left.B / right.B), (byte)(left.A / right.A));
+ }
+
+ public int GetPerceivedBrightness()
+ {
+ return (int)Math.Sqrt(R * R * 0.299 + G * G * 0.587 + B * B * 0.114);
+ }
+
+ public Rgba Intensify(byte component)
+ {
+ byte r = (byte)Math.Min(byte.MaxValue, R + component);
+ byte g = (byte)Math.Min(byte.MaxValue, G + component);
+ byte b = (byte)Math.Min(byte.MaxValue, B + component);
+ byte a = (byte)Math.Min(byte.MaxValue, A + component);
+ return new Rgba(r, g, b, a);
+ }
+
+ public Rgba Desaturate(float f)
+ {
+ float r = R / (float)byte.MaxValue;
+ float g = G / (float)byte.MaxValue;
+ float b = B / (float)byte.MaxValue;
+
+ float l = 0.3f * r + 0.6f * g + 0.1f * b;
+ float newR = r + f * (l - r);
+ float newG = g + f * (l - g);
+ float newB = b + f * (l - b);
+
+ return new Rgba((byte)(newR * byte.MaxValue), (byte)(newG * byte.MaxValue), (byte)(newB * byte.MaxValue), A);
+ }
+
+ public Rgba Darken(float amount)
+ {
+ return new Rgba((byte)(R * (1 - amount)), (byte)(G * (1 - amount)), (byte)(B * (1 - amount)), A);
+ }
+
+ public int GetHue()
+ {
+ byte min = Math.Min(Math.Min(R, G), B);
+ byte max = Math.Max(Math.Max(R, G), B);
+
+ if (min == max)
+ return 0;
+
+ float hue;
+ if (max == R)
+ hue = (G - B) / (float)(max - min);
+ else if (max == G)
+ hue = 2f + (B - R) / (float)(max - min);
+ else
+ hue = 4f + (R - G) / (float)(max - min);
+
+ hue *= 60;
+ if (hue < 0)
+ hue += 360;
+
+ return (int)Math.Round(hue);
+ }
+
+ public static Rgba Lerp(Rgba value1, Rgba value2, float amount)
+ {
+ float r = MathUtils.Lerp(value1.R, value2.R, amount);
+ float g = MathUtils.Lerp(value1.G, value2.G, amount);
+ float b = MathUtils.Lerp(value1.B, value2.B, amount);
+ float a = MathUtils.Lerp(value1.A, value2.A, amount);
+ return new Rgba((byte)r, (byte)g, (byte)b, (byte)a);
+ }
+
+ public static Rgba Invert(Rgba rgba)
+ {
+ return new Rgba((byte)(byte.MaxValue - rgba.R), (byte)(byte.MaxValue - rgba.G), (byte)(byte.MaxValue - rgba.B), rgba.A);
+ }
+
+ public static Rgba Gray(float value)
+ {
+ if (value is < 0 or > 1)
+ throw new ArgumentOutOfRangeException(nameof(value));
+
+ byte component = (byte)(value * byte.MaxValue);
+ return new Rgba(component, component, component);
+ }
+
+ public static Rgba FromHsv(float hue, float saturation, float value)
+ {
+ saturation = Math.Clamp(saturation, 0, 1);
+ value = Math.Clamp(value, 0, 1);
+
+ int hi = (int)MathF.Floor(hue / 60) % 6;
+ float f = hue / 60 - MathF.Floor(hue / 60);
+
+ value *= byte.MaxValue;
+ byte v = (byte)value;
+ byte p = (byte)(value * (1 - saturation));
+ byte q = (byte)(value * (1 - f * saturation));
+ byte t = (byte)(value * (1 - (1 - f) * saturation));
+
+ return hi switch
+ {
+ 0 => new Rgba(v, t, p),
+ 1 => new Rgba(q, v, p),
+ 2 => new Rgba(p, v, t),
+ 3 => new Rgba(p, q, v),
+ 4 => new Rgba(t, p, v),
+ _ => new Rgba(v, p, q),
+ };
+ }
+
+ public static Rgba FromVector3(Vector3 vector)
+ {
+ return new Rgba((byte)(vector.X * byte.MaxValue), (byte)(vector.Y * byte.MaxValue), (byte)(vector.Z * byte.MaxValue));
+ }
+
+ public static Rgba FromVector4(Vector4 vector)
+ {
+ return new Rgba((byte)(vector.X * byte.MaxValue), (byte)(vector.Y * byte.MaxValue), (byte)(vector.Z * byte.MaxValue), (byte)(vector.W * byte.MaxValue));
+ }
+
+ public int ToRgbaInt()
+ {
+ return (R << 24) + (G << 16) + (B << 8) + A;
+ }
+
+ public int ToArgbInt()
+ {
+ return (A << 24) + (R << 16) + (G << 8) + B;
+ }
+
+ public static Rgba FromRgbaInt(int rgba)
+ {
+ return new Rgba((byte)(rgba >> 24), (byte)(rgba >> 16), (byte)(rgba >> 8), (byte)rgba);
+ }
+
+ public static Rgba FromArgbInt(int argb)
+ {
+ return new Rgba((byte)(argb >> 16), (byte)(argb >> 8), (byte)argb, (byte)(argb >> 24));
+ }
+}
diff --git a/src/Detach/Parsers/Texture/TgaFormat/TgaImageData.cs b/src/Detach/Parsers/Texture/TgaFormat/TgaImageData.cs
index 46dd398..149166c 100644
--- a/src/Detach/Parsers/Texture/TgaFormat/TgaImageData.cs
+++ b/src/Detach/Parsers/Texture/TgaFormat/TgaImageData.cs
@@ -57,16 +57,16 @@ public byte[] Read()
if (isRlePacket)
{
- Color color = ReadColor(_pixelDepth, _data.Slice(readPosition, bytesPerPixel).AsSpan());
+ Rgba rgba = ReadRgba(_pixelDepth, _data.Slice(readPosition, bytesPerPixel).AsSpan());
readPosition += bytesPerPixel;
for (int k = 0; k < packetLength; k++)
{
int pixelWriteIndex = (i * _width + j) * 4;
- bytes[pixelWriteIndex + 0] = color.R;
- bytes[pixelWriteIndex + 1] = color.G;
- bytes[pixelWriteIndex + 2] = color.B;
- bytes[pixelWriteIndex + 3] = color.A;
+ bytes[pixelWriteIndex + 0] = rgba.R;
+ bytes[pixelWriteIndex + 1] = rgba.G;
+ bytes[pixelWriteIndex + 2] = rgba.B;
+ bytes[pixelWriteIndex + 3] = rgba.A;
j += columnIncrement;
}
@@ -75,14 +75,14 @@ public byte[] Read()
{
for (int k = 0; k < packetLength; k++)
{
- Color color = ReadColor(_pixelDepth, _data.Slice(readPosition, bytesPerPixel).AsSpan());
+ Rgba rgba = ReadRgba(_pixelDepth, _data.Slice(readPosition, bytesPerPixel).AsSpan());
readPosition += bytesPerPixel;
int pixelWriteIndex = (i * _width + j) * 4;
- bytes[pixelWriteIndex + 0] = color.R;
- bytes[pixelWriteIndex + 1] = color.G;
- bytes[pixelWriteIndex + 2] = color.B;
- bytes[pixelWriteIndex + 3] = color.A;
+ bytes[pixelWriteIndex + 0] = rgba.R;
+ bytes[pixelWriteIndex + 1] = rgba.G;
+ bytes[pixelWriteIndex + 2] = rgba.B;
+ bytes[pixelWriteIndex + 3] = rgba.A;
j += columnIncrement;
}
@@ -99,12 +99,12 @@ public byte[] Read()
for (int j = columnStart; _rightToLeft ? j >= 0 : j < _width; j += columnIncrement)
{
int pixelReadIndex = (i * _width + j) * bytesPerPixel;
- Color color = ReadColor(_pixelDepth, _data.Slice(pixelReadIndex, bytesPerPixel).AsSpan());
+ Rgba rgba = ReadRgba(_pixelDepth, _data.Slice(pixelReadIndex, bytesPerPixel).AsSpan());
- bytes[writePosition + 0] = color.R;
- bytes[writePosition + 1] = color.G;
- bytes[writePosition + 2] = color.B;
- bytes[writePosition + 3] = color.A;
+ bytes[writePosition + 0] = rgba.R;
+ bytes[writePosition + 1] = rgba.G;
+ bytes[writePosition + 2] = rgba.B;
+ bytes[writePosition + 3] = rgba.A;
writePosition += 4;
}
}
@@ -129,13 +129,13 @@ public void Write(BinaryWriter binaryWriter)
{
for (int j = 0; j < _width; j++)
{
- Color currentColor = ReadColor(_pixelDepth, _data.Slice((i * _width + j) * bytesPerPixel, bytesPerPixel).AsSpan());
+ Rgba currentRgba = ReadRgba(_pixelDepth, _data.Slice((i * _width + j) * bytesPerPixel, bytesPerPixel).AsSpan());
int amountOfIdenticalPixels = 1;
while (j + amountOfIdenticalPixels < _width && amountOfIdenticalPixels < 128)
{
- Color nextColor = ReadColor(_pixelDepth, _data.Slice((i * _width + j + amountOfIdenticalPixels) * bytesPerPixel, bytesPerPixel).AsSpan());
- if (currentColor == nextColor)
+ Rgba nextRgba = ReadRgba(_pixelDepth, _data.Slice((i * _width + j + amountOfIdenticalPixels) * bytesPerPixel, bytesPerPixel).AsSpan());
+ if (currentRgba == nextRgba)
amountOfIdenticalPixels++;
else
break;
@@ -150,10 +150,10 @@ public void Write(BinaryWriter binaryWriter)
if (isRlePacket)
{
binaryWriter.Write((byte)(0b1000_0000 | (amountOfIdenticalPixels - 1)));
- binaryWriter.Write(currentColor.R);
- binaryWriter.Write(currentColor.G);
- binaryWriter.Write(currentColor.B);
- binaryWriter.Write(currentColor.A);
+ binaryWriter.Write(currentRgba.R);
+ binaryWriter.Write(currentRgba.G);
+ binaryWriter.Write(currentRgba.B);
+ binaryWriter.Write(currentRgba.A);
}
else
{
@@ -162,22 +162,22 @@ public void Write(BinaryWriter binaryWriter)
for (int k = 0; k < amountOfIdenticalPixels; k++)
{
- binaryWriter.Write(currentColor.R);
- binaryWriter.Write(currentColor.G);
- binaryWriter.Write(currentColor.B);
- binaryWriter.Write(currentColor.A);
+ binaryWriter.Write(currentRgba.R);
+ binaryWriter.Write(currentRgba.G);
+ binaryWriter.Write(currentRgba.B);
+ binaryWriter.Write(currentRgba.A);
}
}
}
}
}
- private static Color ReadColor(TgaPixelDepth pixelDepth, ReadOnlySpan span)
+ private static Rgba ReadRgba(TgaPixelDepth pixelDepth, ReadOnlySpan span)
{
byte b = span[0];
byte g = span[1];
byte r = span[2];
byte a = pixelDepth == TgaPixelDepth.Bgra ? span[3] : (byte)0xFF;
- return new Color(r, g, b, a);
+ return new Rgba(r, g, b, a);
}
}