ryujinx/Ryujinx.Graphics/Texture/ASTCPixel.cs

139 lines
3.8 KiB
C#
Raw Normal View History

using System;
using System.Diagnostics;
namespace Ryujinx.Graphics.Texture
{
class ASTCPixel
{
public short R { get; set; }
public short G { get; set; }
public short B { get; set; }
public short A { get; set; }
byte[] BitDepth = new byte[4];
public ASTCPixel(short _A, short _R, short _G, short _B)
{
A = _A;
R = _R;
G = _G;
B = _B;
for (int i = 0; i < 4; i++)
BitDepth[i] = 8;
}
public void ClampByte()
{
R = Math.Min(Math.Max(R, (short)0), (short)255);
G = Math.Min(Math.Max(G, (short)0), (short)255);
B = Math.Min(Math.Max(B, (short)0), (short)255);
A = Math.Min(Math.Max(A, (short)0), (short)255);
}
public short GetComponent(int Index)
{
switch(Index)
{
case 0: return A;
case 1: return R;
case 2: return G;
case 3: return B;
}
return 0;
}
public void SetComponent(int Index, int Value)
{
switch (Index)
{
case 0:
A = (short)Value;
break;
case 1:
R = (short)Value;
break;
case 2:
G = (short)Value;
break;
case 3:
B = (short)Value;
break;
}
}
public void ChangeBitDepth(byte[] Depth)
{
for(int i = 0; i< 4; i++)
{
int Value = ChangeBitDepth(GetComponent(i), BitDepth[i], Depth[i]);
SetComponent(i, Value);
BitDepth[i] = Depth[i];
}
}
short ChangeBitDepth(short Value, byte OldDepth, byte NewDepth)
{
Debug.Assert(NewDepth <= 8);
Debug.Assert(OldDepth <= 8);
if (OldDepth == NewDepth)
{
// Do nothing
return Value;
}
else if (OldDepth == 0 && NewDepth != 0)
{
return (short)((1 << NewDepth) - 1);
}
else if (NewDepth > OldDepth)
{
return (short)BitArrayStream.Replicate(Value, OldDepth, NewDepth);
}
else
{
// oldDepth > newDepth
if (NewDepth == 0)
{
return 0xFF;
}
else
{
byte BitsWasted = (byte)(OldDepth - NewDepth);
short TempValue = Value;
TempValue = (short)((TempValue + (1 << (BitsWasted - 1))) >> BitsWasted);
TempValue = Math.Min(Math.Max((short)0, TempValue), (short)((1 << NewDepth) - 1));
return (byte)(TempValue);
}
}
}
public int Pack()
{
ASTCPixel NewPixel = new ASTCPixel(A, R, G, B);
byte[] eightBitDepth = { 8, 8, 8, 8 };
NewPixel.ChangeBitDepth(eightBitDepth);
return (byte)NewPixel.A << 24 |
(byte)NewPixel.B << 16 |
(byte)NewPixel.G << 8 |
(byte)NewPixel.R << 0;
}
// Adds more precision to the blue channel as described
// in C.2.14
public static ASTCPixel BlueContract(int a, int r, int g, int b)
{
return new ASTCPixel((short)(a),
(short)((r + b) >> 1),
(short)((g + b) >> 1),
(short)(b));
}
}
}