private unsafe void CopyToArgbAlpha4(SurfaceData surfaceData)
{
// Use a precalculated alpha table for very fast conversions.
var alphaTable = stackalloc byte[16];
for (int i = 0; i < 16; i++)
alphaTable[i] = (byte)(i * (255 * 2185) >> 15); // x / 15 = x * 2185 >> 15 (for 0 ≤ x ≤ 15 * 255)
fixed(byte *dataPointer = data)
fixed(ArgbColor * palettePointer = palette)
{
byte *destinationRowPointer = (byte *)surfaceData.DataPointer;
byte *sourceColorPointer = dataPointer;
byte *sourceAlphaPointer = dataPointer + Width * Height;
byte alphaData = 0;
bool alphaState = false;
for (int i = Height; i-- != 0; destinationRowPointer += surfaceData.Stride)
{
ArgbColor *destinationPointer = (ArgbColor *)destinationRowPointer;
for (int j = Width; j-- != 0;)
{
ArgbColor.CopyWithAlpha(destinationPointer++, palettePointer + *sourceColorPointer++, alphaTable[(alphaState = !alphaState) ? (alphaData = *sourceAlphaPointer++) & 0xF : alphaData >> 4]);
}
}
}
}