private static void Unquantize(ref RgbaColor32 color, int colorDepth, int alphaDepth, int pBit) { color.R = UnquantizeComponent(color.R, colorDepth, pBit); color.G = UnquantizeComponent(color.G, colorDepth, pBit); color.B = UnquantizeComponent(color.B, colorDepth, pBit); color.A = alphaDepth != 0 ? UnquantizeComponent(color.A, alphaDepth, pBit) : 255; }
private static unsafe int GetEndPointSelectionErrorFast(ReadOnlySpan <uint> tile, int subsetCount, int partition, int w, int h, int maxError) { byte[] partitionTable = BC67Tables.PartitionTable[subsetCount - 1][partition]; Span <RgbaColor8> minColors = stackalloc RgbaColor8[subsetCount]; Span <RgbaColor8> maxColors = stackalloc RgbaColor8[subsetCount]; BC67Utils.GetMinMaxColors(partitionTable, tile, w, h, minColors, maxColors, subsetCount); Span <uint> endPoints0 = stackalloc uint[subsetCount]; Span <uint> endPoints1 = stackalloc uint[subsetCount]; SelectEndPointsFast(partitionTable, tile, w, h, subsetCount, minColors, maxColors, endPoints0, endPoints1, uint.MaxValue); Span <RgbaColor32> palette = stackalloc RgbaColor32[8]; int errorSum = 0; for (int subset = 0; subset < subsetCount; subset++) { RgbaColor32 blockDir = maxColors[subset].GetColor32() - minColors[subset].GetColor32(); int sum = blockDir.R + blockDir.G + blockDir.B + blockDir.A; if (sum != 0) { blockDir = (blockDir << 6) / new RgbaColor32(sum); } uint c0 = endPoints0[subset]; uint c1 = endPoints1[subset]; int pBit0 = GetPBit(c0, 6, 0); int pBit1 = GetPBit(c1, 6, 0); c0 = BC67Utils.Quantize(RgbaColor8.FromUInt32(c0), 6, 0, pBit0).ToUInt32(); c1 = BC67Utils.Quantize(RgbaColor8.FromUInt32(c1), 6, 0, pBit1).ToUInt32(); if (Sse41.IsSupported) { Vector128 <byte> c0Rep = Vector128.Create(c0).AsByte(); Vector128 <byte> c1Rep = Vector128.Create(c1).AsByte(); Vector128 <byte> c0c1 = Sse2.UnpackLow(c0Rep, c1Rep); Vector128 <byte> rWeights; Vector128 <byte> lWeights; fixed(byte *pWeights = BC67Tables.Weights[1], pInvWeights = BC67Tables.InverseWeights[1]) { rWeights = Sse2.LoadScalarVector128((ulong *)pWeights).AsByte(); lWeights = Sse2.LoadScalarVector128((ulong *)pInvWeights).AsByte(); } Vector128 <byte> iWeights = Sse2.UnpackLow(rWeights, lWeights); Vector128 <byte> iWeights01 = Sse2.UnpackLow(iWeights.AsInt16(), iWeights.AsInt16()).AsByte(); Vector128 <byte> iWeights23 = Sse2.UnpackHigh(iWeights.AsInt16(), iWeights.AsInt16()).AsByte(); Vector128 <byte> iWeights0 = Sse2.UnpackLow(iWeights01.AsInt16(), iWeights01.AsInt16()).AsByte(); Vector128 <byte> iWeights1 = Sse2.UnpackHigh(iWeights01.AsInt16(), iWeights01.AsInt16()).AsByte(); Vector128 <byte> iWeights2 = Sse2.UnpackLow(iWeights23.AsInt16(), iWeights23.AsInt16()).AsByte(); Vector128 <byte> iWeights3 = Sse2.UnpackHigh(iWeights23.AsInt16(), iWeights23.AsInt16()).AsByte();
private static void DecodeBlock(Block block, Span <uint> output, int w, int h, int width) { int mode = BitOperations.TrailingZeroCount((byte)block.Low | 0x100); if (mode == 8) { // Mode is invalid, the spec mandates that hardware fills the block with // a transparent black color. for (int ty = 0; ty < h; ty++) { int baseOffs = ty * width; for (int tx = 0; tx < w; tx++) { int offs = baseOffs + tx; output[offs] = 0; } } return; } BC7ModeInfo modeInfo = BC67Tables.BC7ModeInfos[mode]; int offset = mode + 1; int partition = (int)block.Decode(ref offset, modeInfo.PartitionBitCount); int rotation = (int)block.Decode(ref offset, modeInfo.RotationBitCount); int indexMode = (int)block.Decode(ref offset, modeInfo.IndexModeBitCount); Debug.Assert(partition < 64); Debug.Assert(rotation < 4); Debug.Assert(indexMode < 2); int endPointCount = modeInfo.SubsetCount * 2; Span <RgbaColor32> endPoints = stackalloc RgbaColor32[endPointCount]; Span <byte> pValues = stackalloc byte[modeInfo.PBits]; endPoints.Fill(new RgbaColor32(0, 0, 0, 255)); for (int i = 0; i < endPointCount; i++) { endPoints[i].R = (int)block.Decode(ref offset, modeInfo.ColorDepth); } for (int i = 0; i < endPointCount; i++) { endPoints[i].G = (int)block.Decode(ref offset, modeInfo.ColorDepth); } for (int i = 0; i < endPointCount; i++) { endPoints[i].B = (int)block.Decode(ref offset, modeInfo.ColorDepth); } if (modeInfo.AlphaDepth != 0) { for (int i = 0; i < endPointCount; i++) { endPoints[i].A = (int)block.Decode(ref offset, modeInfo.AlphaDepth); } } for (int i = 0; i < modeInfo.PBits; i++) { pValues[i] = (byte)block.Decode(ref offset, 1); } for (int i = 0; i < endPointCount; i++) { int pBit = -1; if (modeInfo.PBits != 0) { int pIndex = (i * modeInfo.PBits) / endPointCount; pBit = pValues[pIndex]; } Unquantize(ref endPoints[i], modeInfo.ColorDepth, modeInfo.AlphaDepth, pBit); } byte[] partitionTable = BC67Tables.PartitionTable[modeInfo.SubsetCount - 1][partition]; byte[] fixUpTable = BC67Tables.FixUpIndices[modeInfo.SubsetCount - 1][partition]; Span <byte> colorIndices = stackalloc byte[16]; for (int i = 0; i < 16; i++) { byte subset = partitionTable[i]; int bitCount = i == fixUpTable[subset] ? modeInfo.ColorIndexBitCount - 1 : modeInfo.ColorIndexBitCount; colorIndices[i] = (byte)block.Decode(ref offset, bitCount); Debug.Assert(colorIndices[i] < 16); } Span <byte> alphaIndices = stackalloc byte[16]; if (modeInfo.AlphaIndexBitCount != 0) { for (int i = 0; i < 16; i++) { int bitCount = i != 0 ? modeInfo.AlphaIndexBitCount : modeInfo.AlphaIndexBitCount - 1; alphaIndices[i] = (byte)block.Decode(ref offset, bitCount); Debug.Assert(alphaIndices[i] < 16); } } for (int ty = 0; ty < h; ty++) { int baseOffs = ty * width; for (int tx = 0; tx < w; tx++) { int i = ty * 4 + tx; RgbaColor32 color; byte subset = partitionTable[i]; RgbaColor32 color1 = endPoints[subset * 2]; RgbaColor32 color2 = endPoints[subset * 2 + 1]; if (modeInfo.AlphaIndexBitCount != 0) { if (indexMode == 0) { color = BC67Utils.Interpolate(color1, color2, colorIndices[i], alphaIndices[i], modeInfo.ColorIndexBitCount, modeInfo.AlphaIndexBitCount); } else { color = BC67Utils.Interpolate(color1, color2, alphaIndices[i], colorIndices[i], modeInfo.AlphaIndexBitCount, modeInfo.ColorIndexBitCount); } } else { color = BC67Utils.Interpolate(color1, color2, colorIndices[i], colorIndices[i], modeInfo.ColorIndexBitCount, modeInfo.ColorIndexBitCount); } if (rotation != 0) { int a = color.A; switch (rotation) { case 1: color.A = color.R; color.R = a; break; case 2: color.A = color.G; color.G = a; break; case 3: color.A = color.B; color.B = a; break; } } RgbaColor8 color8 = color.GetColor8(); output[baseOffs + tx] = color8.ToUInt32(); } } }
private static void DecodeBlock(Block block, Span <ulong> output, int w, int h, int width, bool signed) { int mode = (int)(block.Low & 3); if ((mode & 2) != 0) { mode = (int)(block.Low & 0x1f); } Span <RgbaColor32> endPoints = stackalloc RgbaColor32[4]; int subsetCount = DecodeEndPoints(ref block, endPoints, mode, signed); if (subsetCount == 0) { // Mode is invalid, the spec mandates that hardware fills the block with // a opaque black color. for (int ty = 0; ty < h; ty++) { int baseOffs = ty * width; for (int tx = 0; tx < w; tx++) { output[baseOffs + tx] = (ulong)HalfOne << 48; } } return; } int partition; int indexBitCount; ulong indices; if (subsetCount > 1) { partition = (int)((block.High >> 13) & 0x1F); indexBitCount = 3; int fixUpIndex = BC67Tables.FixUpIndices[subsetCount - 1][partition][1] * 3; ulong lowMask = (ulong.MaxValue >> (65 - fixUpIndex)) << 3; ulong highMask = ulong.MaxValue << (fixUpIndex + 3); indices = ((block.High >> 16) & highMask) | ((block.High >> 17) & lowMask) | ((block.High >> 18) & 3); } else { partition = 0; indexBitCount = 4; indices = (block.High & ~0xFUL) | ((block.High >> 1) & 7); } ulong indexMask = (1UL << indexBitCount) - 1; for (int ty = 0; ty < h; ty++) { int baseOffs = ty * width; for (int tx = 0; tx < w; tx++) { int offs = baseOffs + tx; int index = (int)(indices & indexMask); int endPointBase = BC67Tables.PartitionTable[subsetCount - 1][partition][ty * 4 + tx] << 1; RgbaColor32 color1 = endPoints[endPointBase]; RgbaColor32 color2 = endPoints[endPointBase + 1]; RgbaColor32 color = BC67Utils.Interpolate(color1, color2, index, indexBitCount); output[offs] = (ulong)FinishUnquantize(color.R, signed) | ((ulong)FinishUnquantize(color.G, signed) << 16) | ((ulong)FinishUnquantize(color.B, signed) << 32) | ((ulong)HalfOne << 48); indices >>= indexBitCount; } } }
private static int DecodeEndPoints(ref Block block, Span <RgbaColor32> endPoints, int mode, bool signed) { ulong low = block.Low; ulong high = block.High; int r0 = 0, g0 = 0, b0 = 0, r1 = 0, g1 = 0, b1 = 0, r2 = 0, g2 = 0, b2 = 0, r3 = 0, g3 = 0, b3 = 0; int subsetCount; switch (mode) { case 0: r0 = (int)(low >> 5) & 0x3FF; g0 = (int)(low >> 15) & 0x3FF; b0 = (int)(low >> 25) & 0x3FF; if (signed) { r0 = SignExtend(r0, 10); g0 = SignExtend(g0, 10); b0 = SignExtend(b0, 10); } r1 = r0 + SignExtend((int)(low >> 35), 5); g1 = g0 + SignExtend((int)(low >> 45), 5); b1 = b0 + SignExtend((int)(low >> 55), 5); r2 = r0 + SignExtend((int)(high >> 1), 5); g2 = g0 + SignExtend((int)(((low << 2) & 0x10) | ((low >> 41) & 0xF)), 5); b2 = b0 + SignExtend((int)(((low << 1) & 0x10) | ((high << 3) & 0x08) | (low >> 61)), 5); r3 = r0 + SignExtend((int)(high >> 7), 5); g3 = g0 + SignExtend((int)(((low >> 36) & 0x10) | ((low >> 51) & 0xF)), 5); b3 = b0 + SignExtend((int)( ((low) & 0x10) | ((high >> 9) & 0x08) | ((high >> 4) & 0x04) | ((low >> 59) & 0x02) | ((low >> 50) & 0x01)), 5); r0 = Unquantize(r0, 10, signed); g0 = Unquantize(g0, 10, signed); b0 = Unquantize(b0, 10, signed); r1 = Unquantize(r1 & 0x3FF, 10, signed); g1 = Unquantize(g1 & 0x3FF, 10, signed); b1 = Unquantize(b1 & 0x3FF, 10, signed); r2 = Unquantize(r2 & 0x3FF, 10, signed); g2 = Unquantize(g2 & 0x3FF, 10, signed); b2 = Unquantize(b2 & 0x3FF, 10, signed); r3 = Unquantize(r3 & 0x3FF, 10, signed); g3 = Unquantize(g3 & 0x3FF, 10, signed); b3 = Unquantize(b3 & 0x3FF, 10, signed); subsetCount = 2; break; case 1: r0 = (int)(low >> 5) & 0x7F; g0 = (int)(low >> 15) & 0x7F; b0 = (int)(low >> 25) & 0x7F; if (signed) { r0 = SignExtend(r0, 7); g0 = SignExtend(g0, 7); b0 = SignExtend(b0, 7); } r1 = r0 + SignExtend((int)(low >> 35), 6); g1 = g0 + SignExtend((int)(low >> 45), 6); b1 = b0 + SignExtend((int)(low >> 55), 6); r2 = r0 + SignExtend((int)(high >> 1), 6); g2 = g0 + SignExtend((int)(((low << 3) & 0x20) | ((low >> 20) & 0x10) | ((low >> 41) & 0x0F)), 6); b2 = b0 + SignExtend((int)( ((low >> 17) & 0x20) | ((low >> 10) & 0x10) | ((high << 3) & 0x08) | (low >> 61)), 6); r3 = r0 + SignExtend((int)(high >> 7), 6); g3 = g0 + SignExtend((int)(((low << 1) & 0x30) | ((low >> 51) & 0xF)), 6); b3 = b0 + SignExtend((int)( ((low >> 28) & 0x20) | ((low >> 30) & 0x10) | ((low >> 29) & 0x08) | ((low >> 21) & 0x04) | ((low >> 12) & 0x03)), 6); r0 = Unquantize(r0, 7, signed); g0 = Unquantize(g0, 7, signed); b0 = Unquantize(b0, 7, signed); r1 = Unquantize(r1 & 0x7F, 7, signed); g1 = Unquantize(g1 & 0x7F, 7, signed); b1 = Unquantize(b1 & 0x7F, 7, signed); r2 = Unquantize(r2 & 0x7F, 7, signed); g2 = Unquantize(g2 & 0x7F, 7, signed); b2 = Unquantize(b2 & 0x7F, 7, signed); r3 = Unquantize(r3 & 0x7F, 7, signed); g3 = Unquantize(g3 & 0x7F, 7, signed); b3 = Unquantize(b3 & 0x7F, 7, signed); subsetCount = 2; break; case 2: r0 = (int)(((low >> 30) & 0x400) | ((low >> 5) & 0x3FF)); g0 = (int)(((low >> 39) & 0x400) | ((low >> 15) & 0x3FF)); b0 = (int)(((low >> 49) & 0x400) | ((low >> 25) & 0x3FF)); if (signed) { r0 = SignExtend(r0, 11); g0 = SignExtend(g0, 11); b0 = SignExtend(b0, 11); } r1 = r0 + SignExtend((int)(low >> 35), 5); g1 = g0 + SignExtend((int)(low >> 45), 4); b1 = b0 + SignExtend((int)(low >> 55), 4); r2 = r0 + SignExtend((int)(high >> 1), 5); g2 = g0 + SignExtend((int)(low >> 41), 4); b2 = b0 + SignExtend((int)(((high << 3) & 8) | (low >> 61)), 4); r3 = r0 + SignExtend((int)(high >> 7), 5); g3 = g0 + SignExtend((int)(low >> 51), 4); b3 = b0 + SignExtend((int)( ((high >> 9) & 8) | ((high >> 4) & 4) | ((low >> 59) & 2) | ((low >> 50) & 1)), 4); r0 = Unquantize(r0, 11, signed); g0 = Unquantize(g0, 11, signed); b0 = Unquantize(b0, 11, signed); r1 = Unquantize(r1 & 0x7FF, 11, signed); g1 = Unquantize(g1 & 0x7FF, 11, signed); b1 = Unquantize(b1 & 0x7FF, 11, signed); r2 = Unquantize(r2 & 0x7FF, 11, signed); g2 = Unquantize(g2 & 0x7FF, 11, signed); b2 = Unquantize(b2 & 0x7FF, 11, signed); r3 = Unquantize(r3 & 0x7FF, 11, signed); g3 = Unquantize(g3 & 0x7FF, 11, signed); b3 = Unquantize(b3 & 0x7FF, 11, signed); subsetCount = 2; break; case 3: r0 = (int)(low >> 5) & 0x3FF; g0 = (int)(low >> 15) & 0x3FF; b0 = (int)(low >> 25) & 0x3FF; r1 = (int)(low >> 35) & 0x3FF; g1 = (int)(low >> 45) & 0x3FF; b1 = (int)(((high << 9) & 0x200) | (low >> 55)); if (signed) { r0 = SignExtend(r0, 10); g0 = SignExtend(g0, 10); b0 = SignExtend(b0, 10); r1 = SignExtend(r1, 10); g1 = SignExtend(g1, 10); b1 = SignExtend(b1, 10); } r0 = Unquantize(r0, 10, signed); g0 = Unquantize(g0, 10, signed); b0 = Unquantize(b0, 10, signed); r1 = Unquantize(r1, 10, signed); g1 = Unquantize(g1, 10, signed); b1 = Unquantize(b1, 10, signed); subsetCount = 1; break; case 6: r0 = (int)(((low >> 29) & 0x400) | ((low >> 5) & 0x3FF)); g0 = (int)(((low >> 40) & 0x400) | ((low >> 15) & 0x3FF)); b0 = (int)(((low >> 49) & 0x400) | ((low >> 25) & 0x3FF)); if (signed) { r0 = SignExtend(r0, 11); g0 = SignExtend(g0, 11); b0 = SignExtend(b0, 11); } r1 = r0 + SignExtend((int)(low >> 35), 4); g1 = g0 + SignExtend((int)(low >> 45), 5); b1 = b0 + SignExtend((int)(low >> 55), 4); r2 = r0 + SignExtend((int)(high >> 1), 4); g2 = g0 + SignExtend((int)(((high >> 7) & 0x10) | ((low >> 41) & 0x0F)), 5); b2 = b0 + SignExtend((int)(((high << 3) & 0x08) | ((low >> 61))), 4); r3 = r0 + SignExtend((int)(high >> 7), 4); g3 = g0 + SignExtend((int)(((low >> 36) & 0x10) | ((low >> 51) & 0x0F)), 5); b3 = b0 + SignExtend((int)( ((high >> 9) & 8) | ((high >> 4) & 4) | ((low >> 59) & 2) | ((high >> 5) & 1)), 4); r0 = Unquantize(r0, 11, signed); g0 = Unquantize(g0, 11, signed); b0 = Unquantize(b0, 11, signed); r1 = Unquantize(r1 & 0x7FF, 11, signed); g1 = Unquantize(g1 & 0x7FF, 11, signed); b1 = Unquantize(b1 & 0x7FF, 11, signed); r2 = Unquantize(r2 & 0x7FF, 11, signed); g2 = Unquantize(g2 & 0x7FF, 11, signed); b2 = Unquantize(b2 & 0x7FF, 11, signed); r3 = Unquantize(r3 & 0x7FF, 11, signed); g3 = Unquantize(g3 & 0x7FF, 11, signed); b3 = Unquantize(b3 & 0x7FF, 11, signed); subsetCount = 2; break; case 7: r0 = (int)(((low >> 34) & 0x400) | ((low >> 5) & 0x3FF)); g0 = (int)(((low >> 44) & 0x400) | ((low >> 15) & 0x3FF)); b0 = (int)(((high << 10) & 0x400) | ((low >> 25) & 0x3FF)); if (signed) { r0 = SignExtend(r0, 11); g0 = SignExtend(g0, 11); b0 = SignExtend(b0, 11); } r1 = (r0 + SignExtend((int)(low >> 35), 9)) & 0x7FF; g1 = (g0 + SignExtend((int)(low >> 45), 9)) & 0x7FF; b1 = (b0 + SignExtend((int)(low >> 55), 9)) & 0x7FF; r0 = Unquantize(r0, 11, signed); g0 = Unquantize(g0, 11, signed); b0 = Unquantize(b0, 11, signed); r1 = Unquantize(r1, 11, signed); g1 = Unquantize(g1, 11, signed); b1 = Unquantize(b1, 11, signed); subsetCount = 1; break; case 10: r0 = (int)(((low >> 29) & 0x400) | ((low >> 5) & 0x3FF)); g0 = (int)(((low >> 39) & 0x400) | ((low >> 15) & 0x3FF)); b0 = (int)(((low >> 50) & 0x400) | ((low >> 25) & 0x3FF)); if (signed) { r0 = SignExtend(r0, 11); g0 = SignExtend(g0, 11); b0 = SignExtend(b0, 11); } r1 = r0 + SignExtend((int)(low >> 35), 4); g1 = g0 + SignExtend((int)(low >> 45), 4); b1 = b0 + SignExtend((int)(low >> 55), 5); r2 = r0 + SignExtend((int)(high >> 1), 4); g2 = g0 + SignExtend((int)(low >> 41), 4); b2 = b0 + SignExtend((int)(((low >> 36) & 0x10) | ((high << 3) & 8) | (low >> 61)), 5); r3 = r0 + SignExtend((int)(high >> 7), 4); g3 = g0 + SignExtend((int)(low >> 51), 4); b3 = b0 + SignExtend((int)( ((high >> 7) & 0x10) | ((high >> 9) & 0x08) | ((high >> 4) & 0x06) | ((low >> 50) & 0x01)), 5); r0 = Unquantize(r0, 11, signed); g0 = Unquantize(g0, 11, signed); b0 = Unquantize(b0, 11, signed); r1 = Unquantize(r1 & 0x7FF, 11, signed); g1 = Unquantize(g1 & 0x7FF, 11, signed); b1 = Unquantize(b1 & 0x7FF, 11, signed); r2 = Unquantize(r2 & 0x7FF, 11, signed); g2 = Unquantize(g2 & 0x7FF, 11, signed); b2 = Unquantize(b2 & 0x7FF, 11, signed); r3 = Unquantize(r3 & 0x7FF, 11, signed); g3 = Unquantize(g3 & 0x7FF, 11, signed); b3 = Unquantize(b3 & 0x7FF, 11, signed); subsetCount = 2; break; case 11: r0 = (int)(((low >> 32) & 0x800) | ((low >> 34) & 0x400) | ((low >> 5) & 0x3FF)); g0 = (int)(((low >> 42) & 0x800) | ((low >> 44) & 0x400) | ((low >> 15) & 0x3FF)); b0 = (int)(((low >> 52) & 0x800) | ((high << 10) & 0x400) | ((low >> 25) & 0x3FF)); if (signed) { r0 = SignExtend(r0, 12); g0 = SignExtend(g0, 12); b0 = SignExtend(b0, 12); } r1 = (r0 + SignExtend((int)(low >> 35), 8)) & 0xFFF; g1 = (g0 + SignExtend((int)(low >> 45), 8)) & 0xFFF; b1 = (b0 + SignExtend((int)(low >> 55), 8)) & 0xFFF; r0 = Unquantize(r0, 12, signed); g0 = Unquantize(g0, 12, signed); b0 = Unquantize(b0, 12, signed); r1 = Unquantize(r1, 12, signed); g1 = Unquantize(g1, 12, signed); b1 = Unquantize(b1, 12, signed); subsetCount = 1; break; case 14: r0 = (int)(low >> 5) & 0x1FF; g0 = (int)(low >> 15) & 0x1FF; b0 = (int)(low >> 25) & 0x1FF; if (signed) { r0 = SignExtend(r0, 9); g0 = SignExtend(g0, 9); b0 = SignExtend(b0, 9); } r1 = r0 + SignExtend((int)(low >> 35), 5); g1 = g0 + SignExtend((int)(low >> 45), 5); b1 = b0 + SignExtend((int)(low >> 55), 5); r2 = r0 + SignExtend((int)(high >> 1), 5); g2 = g0 + SignExtend((int)(((low >> 20) & 0x10) | ((low >> 41) & 0xF)), 5); b2 = b0 + SignExtend((int)(((low >> 10) & 0x10) | ((high << 3) & 8) | (low >> 61)), 5); r3 = r0 + SignExtend((int)(high >> 7), 5); g3 = g0 + SignExtend((int)(((low >> 36) & 0x10) | ((low >> 51) & 0xF)), 5); b3 = b0 + SignExtend((int)( ((low >> 30) & 0x10) | ((high >> 9) & 0x08) | ((high >> 4) & 0x04) | ((low >> 59) & 0x02) | ((low >> 50) & 0x01)), 5); r0 = Unquantize(r0, 9, signed); g0 = Unquantize(g0, 9, signed); b0 = Unquantize(b0, 9, signed); r1 = Unquantize(r1 & 0x1FF, 9, signed); g1 = Unquantize(g1 & 0x1FF, 9, signed); b1 = Unquantize(b1 & 0x1FF, 9, signed); r2 = Unquantize(r2 & 0x1FF, 9, signed); g2 = Unquantize(g2 & 0x1FF, 9, signed); b2 = Unquantize(b2 & 0x1FF, 9, signed); r3 = Unquantize(r3 & 0x1FF, 9, signed); g3 = Unquantize(g3 & 0x1FF, 9, signed); b3 = Unquantize(b3 & 0x1FF, 9, signed); subsetCount = 2; break; case 15: r0 = (BitReverse6((int)(low >> 39) & 0x3F) << 10) | ((int)(low >> 5) & 0x3FF); g0 = (BitReverse6((int)(low >> 49) & 0x3F) << 10) | ((int)(low >> 15) & 0x3FF); b0 = ((BitReverse6((int)(low >> 59)) | (int)(high & 1)) << 10) | ((int)(low >> 25) & 0x3FF); if (signed) { r0 = SignExtend(r0, 16); g0 = SignExtend(g0, 16); b0 = SignExtend(b0, 16); } r1 = (r0 + SignExtend((int)(low >> 35), 4)) & 0xFFFF; g1 = (g0 + SignExtend((int)(low >> 45), 4)) & 0xFFFF; b1 = (b0 + SignExtend((int)(low >> 55), 4)) & 0xFFFF; subsetCount = 1; break; case 18: r0 = (int)(low >> 5) & 0xFF; g0 = (int)(low >> 15) & 0xFF; b0 = (int)(low >> 25) & 0xFF; if (signed) { r0 = SignExtend(r0, 8); g0 = SignExtend(g0, 8); b0 = SignExtend(b0, 8); } r1 = r0 + SignExtend((int)(low >> 35), 6); g1 = g0 + SignExtend((int)(low >> 45), 5); b1 = b0 + SignExtend((int)(low >> 55), 5); r2 = r0 + SignExtend((int)(high >> 1), 6); g2 = g0 + SignExtend((int)(((low >> 20) & 0x10) | ((low >> 41) & 0xF)), 5); b2 = b0 + SignExtend((int)(((low >> 10) & 0x10) | ((high << 3) & 8) | (low >> 61)), 5); r3 = r0 + SignExtend((int)(high >> 7), 6); g3 = g0 + SignExtend((int)(((low >> 9) & 0x10) | ((low >> 51) & 0xF)), 5); b3 = b0 + SignExtend((int)( ((low >> 30) & 0x18) | ((low >> 21) & 0x04) | ((low >> 59) & 0x02) | ((low >> 50) & 0x01)), 5); r0 = Unquantize(r0, 8, signed); g0 = Unquantize(g0, 8, signed); b0 = Unquantize(b0, 8, signed); r1 = Unquantize(r1 & 0xFF, 8, signed); g1 = Unquantize(g1 & 0xFF, 8, signed); b1 = Unquantize(b1 & 0xFF, 8, signed); r2 = Unquantize(r2 & 0xFF, 8, signed); g2 = Unquantize(g2 & 0xFF, 8, signed); b2 = Unquantize(b2 & 0xFF, 8, signed); r3 = Unquantize(r3 & 0xFF, 8, signed); g3 = Unquantize(g3 & 0xFF, 8, signed); b3 = Unquantize(b3 & 0xFF, 8, signed); subsetCount = 2; break; case 22: r0 = (int)(low >> 5) & 0xFF; g0 = (int)(low >> 15) & 0xFF; b0 = (int)(low >> 25) & 0xFF; if (signed) { r0 = SignExtend(r0, 8); g0 = SignExtend(g0, 8); b0 = SignExtend(b0, 8); } r1 = r0 + SignExtend((int)(low >> 35), 5); g1 = g0 + SignExtend((int)(low >> 45), 6); b1 = b0 + SignExtend((int)(low >> 55), 5); r2 = r0 + SignExtend((int)(high >> 1), 5); g2 = g0 + SignExtend((int)(((low >> 18) & 0x20) | ((low >> 20) & 0x10) | ((low >> 41) & 0xF)), 6); b2 = b0 + SignExtend((int)(((low >> 10) & 0x10) | ((high << 3) & 0x08) | (low >> 61)), 5); r3 = r0 + SignExtend((int)(high >> 7), 5); g3 = g0 + SignExtend((int)(((low >> 28) & 0x20) | ((low >> 36) & 0x10) | ((low >> 51) & 0x0F)), 6); b3 = b0 + SignExtend((int)( ((low >> 30) & 0x10) | ((high >> 9) & 0x08) | ((high >> 4) & 0x04) | ((low >> 59) & 0x02) | ((low >> 13) & 0x01)), 5); r0 = Unquantize(r0, 8, signed); g0 = Unquantize(g0, 8, signed); b0 = Unquantize(b0, 8, signed); r1 = Unquantize(r1 & 0xFF, 8, signed); g1 = Unquantize(g1 & 0xFF, 8, signed); b1 = Unquantize(b1 & 0xFF, 8, signed); r2 = Unquantize(r2 & 0xFF, 8, signed); g2 = Unquantize(g2 & 0xFF, 8, signed); b2 = Unquantize(b2 & 0xFF, 8, signed); r3 = Unquantize(r3 & 0xFF, 8, signed); g3 = Unquantize(g3 & 0xFF, 8, signed); b3 = Unquantize(b3 & 0xFF, 8, signed); subsetCount = 2; break; case 26: r0 = (int)(low >> 5) & 0xFF; g0 = (int)(low >> 15) & 0xFF; b0 = (int)(low >> 25) & 0xFF; if (signed) { r0 = SignExtend(r0, 8); g0 = SignExtend(g0, 8); b0 = SignExtend(b0, 8); } r1 = r0 + SignExtend((int)(low >> 35), 5); g1 = g0 + SignExtend((int)(low >> 45), 5); b1 = b0 + SignExtend((int)(low >> 55), 6); r2 = r0 + SignExtend((int)(high >> 1), 5); g2 = g0 + SignExtend((int)(((low >> 20) & 0x10) | ((low >> 41) & 0xF)), 5); b2 = b0 + SignExtend((int)( ((low >> 18) & 0x20) | ((low >> 10) & 0x10) | ((high << 3) & 0x08) | (low >> 61)), 6); r3 = r0 + SignExtend((int)(high >> 7), 5); g3 = g0 + SignExtend((int)(((low >> 36) & 0x10) | ((low >> 51) & 0xF)), 5); b3 = b0 + SignExtend((int)( ((low >> 28) & 0x20) | ((low >> 30) & 0x10) | ((high >> 9) & 0x08) | ((high >> 4) & 0x04) | ((low >> 12) & 0x02) | ((low >> 50) & 0x01)), 6); r0 = Unquantize(r0, 8, signed); g0 = Unquantize(g0, 8, signed); b0 = Unquantize(b0, 8, signed); r1 = Unquantize(r1 & 0xFF, 8, signed); g1 = Unquantize(g1 & 0xFF, 8, signed); b1 = Unquantize(b1 & 0xFF, 8, signed); r2 = Unquantize(r2 & 0xFF, 8, signed); g2 = Unquantize(g2 & 0xFF, 8, signed); b2 = Unquantize(b2 & 0xFF, 8, signed); r3 = Unquantize(r3 & 0xFF, 8, signed); g3 = Unquantize(g3 & 0xFF, 8, signed); b3 = Unquantize(b3 & 0xFF, 8, signed); subsetCount = 2; break; case 30: r0 = (int)(low >> 5) & 0x3F; g0 = (int)(low >> 15) & 0x3F; b0 = (int)(low >> 25) & 0x3F; r1 = (int)(low >> 35) & 0x3F; g1 = (int)(low >> 45) & 0x3F; b1 = (int)(low >> 55) & 0x3F; r2 = (int)(high >> 1) & 0x3F; g2 = (int)(((low >> 16) & 0x20) | ((low >> 20) & 0x10) | ((low >> 41) & 0xF)); b2 = (int)(((low >> 17) & 0x20) | ((low >> 10) & 0x10) | ((high << 3) & 0x08) | (low >> 61)); r3 = (int)(high >> 7) & 0x3F; g3 = (int)(((low >> 26) & 0x20) | ((low >> 7) & 0x10) | ((low >> 51) & 0xF)); b3 = (int)( ((low >> 28) & 0x20) | ((low >> 30) & 0x10) | ((low >> 29) & 0x08) | ((low >> 21) & 0x04) | ((low >> 12) & 0x03)); if (signed) { r0 = SignExtend(r0, 6); g0 = SignExtend(g0, 6); b0 = SignExtend(b0, 6); r1 = SignExtend(r1, 6); g1 = SignExtend(g1, 6); b1 = SignExtend(b1, 6); r2 = SignExtend(r2, 6); g2 = SignExtend(g2, 6); b2 = SignExtend(b2, 6); r3 = SignExtend(r3, 6); g3 = SignExtend(g3, 6); b3 = SignExtend(b3, 6); } r0 = Unquantize(r0, 6, signed); g0 = Unquantize(g0, 6, signed); b0 = Unquantize(b0, 6, signed); r1 = Unquantize(r1, 6, signed); g1 = Unquantize(g1, 6, signed); b1 = Unquantize(b1, 6, signed); r2 = Unquantize(r2, 6, signed); g2 = Unquantize(g2, 6, signed); b2 = Unquantize(b2, 6, signed); r3 = Unquantize(r3, 6, signed); g3 = Unquantize(g3, 6, signed); b3 = Unquantize(b3, 6, signed); subsetCount = 2; break; default: subsetCount = 0; break; } if (subsetCount > 0) { endPoints[0] = new RgbaColor32(r0, g0, b0, HalfOne); endPoints[1] = new RgbaColor32(r1, g1, b1, HalfOne); if (subsetCount > 1) { endPoints[2] = new RgbaColor32(r2, g2, b2, HalfOne); endPoints[3] = new RgbaColor32(r3, g3, b3, HalfOne); } } return(subsetCount); }