IntegerEncoded.cs 8.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269
  1. using System.Collections;
  2. using System.Collections.Generic;
  3. namespace Ryujinx.Graphics.Texture
  4. {
  5. public struct IntegerEncoded
  6. {
  7. public enum EIntegerEncoding
  8. {
  9. JustBits,
  10. Quint,
  11. Trit
  12. }
  13. EIntegerEncoding Encoding;
  14. public int NumberBits { get; private set; }
  15. public int BitValue { get; private set; }
  16. public int TritValue { get; private set; }
  17. public int QuintValue { get; private set; }
  18. public IntegerEncoded(EIntegerEncoding _Encoding, int NumBits)
  19. {
  20. Encoding = _Encoding;
  21. NumberBits = NumBits;
  22. BitValue = 0;
  23. TritValue = 0;
  24. QuintValue = 0;
  25. }
  26. public bool MatchesEncoding(IntegerEncoded Other)
  27. {
  28. return Encoding == Other.Encoding && NumberBits == Other.NumberBits;
  29. }
  30. public EIntegerEncoding GetEncoding()
  31. {
  32. return Encoding;
  33. }
  34. public int GetBitLength(int NumberVals)
  35. {
  36. int TotalBits = NumberBits * NumberVals;
  37. if (Encoding == EIntegerEncoding.Trit)
  38. {
  39. TotalBits += (NumberVals * 8 + 4) / 5;
  40. }
  41. else if (Encoding == EIntegerEncoding.Quint)
  42. {
  43. TotalBits += (NumberVals * 7 + 2) / 3;
  44. }
  45. return TotalBits;
  46. }
  47. public static IntegerEncoded CreateEncoding(int MaxVal)
  48. {
  49. while (MaxVal > 0)
  50. {
  51. int Check = MaxVal + 1;
  52. // Is maxVal a power of two?
  53. if ((Check & (Check - 1)) == 0)
  54. {
  55. return new IntegerEncoded(EIntegerEncoding.JustBits, BitArrayStream.PopCnt(MaxVal));
  56. }
  57. // Is maxVal of the type 3*2^n - 1?
  58. if ((Check % 3 == 0) && ((Check / 3) & ((Check / 3) - 1)) == 0)
  59. {
  60. return new IntegerEncoded(EIntegerEncoding.Trit, BitArrayStream.PopCnt(Check / 3 - 1));
  61. }
  62. // Is maxVal of the type 5*2^n - 1?
  63. if ((Check % 5 == 0) && ((Check / 5) & ((Check / 5) - 1)) == 0)
  64. {
  65. return new IntegerEncoded(EIntegerEncoding.Quint, BitArrayStream.PopCnt(Check / 5 - 1));
  66. }
  67. // Apparently it can't be represented with a bounded integer sequence...
  68. // just iterate.
  69. MaxVal--;
  70. }
  71. return new IntegerEncoded(EIntegerEncoding.JustBits, 0);
  72. }
  73. public static void DecodeTritBlock(
  74. BitArrayStream BitStream,
  75. List<IntegerEncoded> ListIntegerEncoded,
  76. int NumberBitsPerValue)
  77. {
  78. // Implement the algorithm in section C.2.12
  79. int[] m = new int[5];
  80. int[] t = new int[5];
  81. int T;
  82. // Read the trit encoded block according to
  83. // table C.2.14
  84. m[0] = BitStream.ReadBits(NumberBitsPerValue);
  85. T = BitStream.ReadBits(2);
  86. m[1] = BitStream.ReadBits(NumberBitsPerValue);
  87. T |= BitStream.ReadBits(2) << 2;
  88. m[2] = BitStream.ReadBits(NumberBitsPerValue);
  89. T |= BitStream.ReadBits(1) << 4;
  90. m[3] = BitStream.ReadBits(NumberBitsPerValue);
  91. T |= BitStream.ReadBits(2) << 5;
  92. m[4] = BitStream.ReadBits(NumberBitsPerValue);
  93. T |= BitStream.ReadBits(1) << 7;
  94. int C = 0;
  95. BitArrayStream Tb = new BitArrayStream(new BitArray(new int[] { T }));
  96. if (Tb.ReadBits(2, 4) == 7)
  97. {
  98. C = (Tb.ReadBits(5, 7) << 2) | Tb.ReadBits(0, 1);
  99. t[4] = t[3] = 2;
  100. }
  101. else
  102. {
  103. C = Tb.ReadBits(0, 4);
  104. if (Tb.ReadBits(5, 6) == 3)
  105. {
  106. t[4] = 2;
  107. t[3] = Tb.ReadBit(7);
  108. }
  109. else
  110. {
  111. t[4] = Tb.ReadBit(7);
  112. t[3] = Tb.ReadBits(5, 6);
  113. }
  114. }
  115. BitArrayStream Cb = new BitArrayStream(new BitArray(new int[] { C }));
  116. if (Cb.ReadBits(0, 1) == 3)
  117. {
  118. t[2] = 2;
  119. t[1] = Cb.ReadBit(4);
  120. t[0] = (Cb.ReadBit(3) << 1) | (Cb.ReadBit(2) & ~Cb.ReadBit(3));
  121. }
  122. else if (Cb.ReadBits(2, 3) == 3)
  123. {
  124. t[2] = 2;
  125. t[1] = 2;
  126. t[0] = Cb.ReadBits(0, 1);
  127. }
  128. else
  129. {
  130. t[2] = Cb.ReadBit(4);
  131. t[1] = Cb.ReadBits(2, 3);
  132. t[0] = (Cb.ReadBit(1) << 1) | (Cb.ReadBit(0) & ~Cb.ReadBit(1));
  133. }
  134. for (int i = 0; i < 5; i++)
  135. {
  136. IntegerEncoded IntEncoded = new IntegerEncoded(EIntegerEncoding.Trit, NumberBitsPerValue)
  137. {
  138. BitValue = m[i],
  139. TritValue = t[i]
  140. };
  141. ListIntegerEncoded.Add(IntEncoded);
  142. }
  143. }
  144. public static void DecodeQuintBlock(
  145. BitArrayStream BitStream,
  146. List<IntegerEncoded> ListIntegerEncoded,
  147. int NumberBitsPerValue)
  148. {
  149. // Implement the algorithm in section C.2.12
  150. int[] m = new int[3];
  151. int[] q = new int[3];
  152. int Q;
  153. // Read the trit encoded block according to
  154. // table C.2.15
  155. m[0] = BitStream.ReadBits(NumberBitsPerValue);
  156. Q = BitStream.ReadBits(3);
  157. m[1] = BitStream.ReadBits(NumberBitsPerValue);
  158. Q |= BitStream.ReadBits(2) << 3;
  159. m[2] = BitStream.ReadBits(NumberBitsPerValue);
  160. Q |= BitStream.ReadBits(2) << 5;
  161. BitArrayStream Qb = new BitArrayStream(new BitArray(new int[] { Q }));
  162. if (Qb.ReadBits(1, 2) == 3 && Qb.ReadBits(5, 6) == 0)
  163. {
  164. q[0] = q[1] = 4;
  165. q[2] = (Qb.ReadBit(0) << 2) | ((Qb.ReadBit(4) & ~Qb.ReadBit(0)) << 1) | (Qb.ReadBit(3) & ~Qb.ReadBit(0));
  166. }
  167. else
  168. {
  169. int C = 0;
  170. if (Qb.ReadBits(1, 2) == 3)
  171. {
  172. q[2] = 4;
  173. C = (Qb.ReadBits(3, 4) << 3) | ((~Qb.ReadBits(5, 6) & 3) << 1) | Qb.ReadBit(0);
  174. }
  175. else
  176. {
  177. q[2] = Qb.ReadBits(5, 6);
  178. C = Qb.ReadBits(0, 4);
  179. }
  180. BitArrayStream Cb = new BitArrayStream(new BitArray(new int[] { C }));
  181. if (Cb.ReadBits(0, 2) == 5)
  182. {
  183. q[1] = 4;
  184. q[0] = Cb.ReadBits(3, 4);
  185. }
  186. else
  187. {
  188. q[1] = Cb.ReadBits(3, 4);
  189. q[0] = Cb.ReadBits(0, 2);
  190. }
  191. }
  192. for (int i = 0; i < 3; i++)
  193. {
  194. IntegerEncoded IntEncoded = new IntegerEncoded(EIntegerEncoding.Quint, NumberBitsPerValue)
  195. {
  196. BitValue = m[i],
  197. QuintValue = q[i]
  198. };
  199. ListIntegerEncoded.Add(IntEncoded);
  200. }
  201. }
  202. public static void DecodeIntegerSequence(
  203. List<IntegerEncoded> DecodeIntegerSequence,
  204. BitArrayStream BitStream,
  205. int MaxRange,
  206. int NumberValues)
  207. {
  208. // Determine encoding parameters
  209. IntegerEncoded IntEncoded = CreateEncoding(MaxRange);
  210. // Start decoding
  211. int NumberValuesDecoded = 0;
  212. while (NumberValuesDecoded < NumberValues)
  213. {
  214. switch (IntEncoded.GetEncoding())
  215. {
  216. case EIntegerEncoding.Quint:
  217. {
  218. DecodeQuintBlock(BitStream, DecodeIntegerSequence, IntEncoded.NumberBits);
  219. NumberValuesDecoded += 3;
  220. break;
  221. }
  222. case EIntegerEncoding.Trit:
  223. {
  224. DecodeTritBlock(BitStream, DecodeIntegerSequence, IntEncoded.NumberBits);
  225. NumberValuesDecoded += 5;
  226. break;
  227. }
  228. case EIntegerEncoding.JustBits:
  229. {
  230. IntEncoded.BitValue = BitStream.ReadBits(IntEncoded.NumberBits);
  231. DecodeIntegerSequence.Add(IntEncoded);
  232. NumberValuesDecoded++;
  233. break;
  234. }
  235. }
  236. }
  237. }
  238. }
  239. }