Пример #1
0
        private static LDRColorA Unquantize(LDRColorA c, LDRColorA RGBAPrec)
        {
            LDRColorA q = new LDRColorA();

            q.r = Unquantize(c.r, RGBAPrec.r);
            q.g = Unquantize(c.g, RGBAPrec.g);
            q.b = Unquantize(c.b, RGBAPrec.b);
            q.a = RGBAPrec.a > 0 ? Unquantize(c.a, RGBAPrec.a) : (byte)255u;
            return(q);
        }
Пример #2
0
 public ModeInfo(byte uParts, byte uPartBits, byte upBits, byte uRotBits, byte uIndModeBits, byte uIndPrec, byte uIndPrec2, LDRColorA rgbaPrec, LDRColorA rgbaPrecWithP)
 {
     uPartitions    = uParts;
     uPartitionBits = uPartBits;
     uPBits         = upBits;
     uRotationBits  = uRotBits;
     uIndexModeBits = uIndModeBits;
     uIndexPrec     = uIndPrec;
     uIndexPrec2    = uIndPrec2;
     RGBAPrec       = rgbaPrec;
     RGBAPrecWithP  = rgbaPrecWithP;
 }
Пример #3
0
        protected override int Decode(byte[] stream, byte[] data, int streamIndex, uint dataIndex, uint stride)
        {
            // I would prefer to use Span, but not sure if I should reference System.Memory in this project
            // copy data instead
            Buffer.BlockCopy(stream, streamIndex, currentBlock, 0, currentBlock.Length);
            streamIndex += currentBlock.Length;

            uint uFirst = 0;

            while (uFirst < 128 && GetBit(ref uFirst) == 0)
            {
            }
            byte uMode = (byte)(uFirst - 1);

            if (uMode < 8)
            {
                byte uPartitions = ms_aInfo[uMode].uPartitions;
                Debug.Assert(uPartitions < Constants.BC7_MAX_REGIONS);

                var   uNumEndPts  = (byte)((uPartitions + 1u) << 1);
                byte  uIndexPrec  = ms_aInfo[uMode].uIndexPrec;
                byte  uIndexPrec2 = ms_aInfo[uMode].uIndexPrec2;
                int   i;
                uint  uStartBit = uMode + 1u;
                int[] P         = new int[6];
                byte  uShape    = GetBits(ref uStartBit, ms_aInfo[uMode].uPartitionBits);
                Debug.Assert(uShape < Constants.BC7_MAX_SHAPES);

                byte uRotation = GetBits(ref uStartBit, ms_aInfo[uMode].uRotationBits);
                Debug.Assert(uRotation < 4);

                byte uIndexMode = GetBits(ref uStartBit, ms_aInfo[uMode].uIndexModeBits);
                Debug.Assert(uIndexMode < 2);

                LDRColorA[] c = new LDRColorA[Constants.BC7_MAX_REGIONS << 1];
                for (i = 0; i < c.Length; ++i)
                {
                    c[i] = new LDRColorA();
                }
                LDRColorA RGBAPrec      = ms_aInfo[uMode].RGBAPrec;
                LDRColorA RGBAPrecWithP = ms_aInfo[uMode].RGBAPrecWithP;

                Debug.Assert(uNumEndPts <= (Constants.BC7_MAX_REGIONS << 1));

                // Red channel
                for (i = 0; i < uNumEndPts; i++)
                {
                    if (uStartBit + RGBAPrec.r > 128)
                    {
                        Debug.WriteLine("BC7: Invalid block encountered during decoding");
                        Helpers.FillWithErrorColors(data, ref dataIndex, Constants.NUM_PIXELS_PER_BLOCK, DivSize, stride);
                        return(streamIndex);
                    }

                    c[i].r = GetBits(ref uStartBit, RGBAPrec.r);
                }

                // Green channel
                for (i = 0; i < uNumEndPts; i++)
                {
                    if (uStartBit + RGBAPrec.g > 128)
                    {
                        Debug.WriteLine("BC7: Invalid block encountered during decoding");
                        Helpers.FillWithErrorColors(data, ref dataIndex, Constants.NUM_PIXELS_PER_BLOCK, DivSize, stride);
                        return(streamIndex);
                    }

                    c[i].g = GetBits(ref uStartBit, RGBAPrec.g);
                }

                // Blue channel
                for (i = 0; i < uNumEndPts; i++)
                {
                    if (uStartBit + RGBAPrec.b > 128)
                    {
                        Debug.WriteLine("BC7: Invalid block encountered during decoding");
                        Helpers.FillWithErrorColors(data, ref dataIndex, Constants.NUM_PIXELS_PER_BLOCK, DivSize, stride);
                        return(streamIndex);
                    }

                    c[i].b = GetBits(ref uStartBit, RGBAPrec.b);
                }

                // Alpha channel
                for (i = 0; i < uNumEndPts; i++)
                {
                    if (uStartBit + RGBAPrec.a > 128)
                    {
                        Debug.WriteLine("BC7: Invalid block encountered during decoding");
                        Helpers.FillWithErrorColors(data, ref dataIndex, Constants.NUM_PIXELS_PER_BLOCK, DivSize, stride);
                        return(streamIndex);
                    }

                    c[i].a = (byte)(RGBAPrec.a != 0 ? GetBits(ref uStartBit, RGBAPrec.a) : 255u);
                }

                // P-bits
                Debug.Assert(ms_aInfo[uMode].uPBits <= 6);
                for (i = 0; i < ms_aInfo[uMode].uPBits; i++)
                {
                    if (uStartBit > 127)
                    {
                        Debug.WriteLine("BC7: Invalid block encountered during decoding");
                        Helpers.FillWithErrorColors(data, ref dataIndex, Constants.NUM_PIXELS_PER_BLOCK, DivSize, stride);
                        return(streamIndex);
                    }

                    P[i] = GetBit(ref uStartBit);
                }

                if (ms_aInfo[uMode].uPBits != 0)
                {
                    for (i = 0; i < uNumEndPts; i++)
                    {
                        int pi = i * ms_aInfo[uMode].uPBits / uNumEndPts;
                        for (byte ch = 0; ch < Constants.BC7_NUM_CHANNELS; ch++)
                        {
                            if (RGBAPrec[ch] != RGBAPrecWithP[ch])
                            {
                                c[i][ch] = (byte)((c[i][ch] << 1) | P[pi]);
                            }
                        }
                    }
                }

                for (i = 0; i < uNumEndPts; i++)
                {
                    c[i] = Unquantize(c[i], RGBAPrecWithP);
                }

                byte[] w1 = new byte[Constants.NUM_PIXELS_PER_BLOCK], w2 = new byte[Constants.NUM_PIXELS_PER_BLOCK];

                // read color indices
                for (i = 0; i < Constants.NUM_PIXELS_PER_BLOCK; i++)
                {
                    uint uNumBits = Helpers.IsFixUpOffset(ms_aInfo[uMode].uPartitions, uShape, i) ? uIndexPrec - 1u : uIndexPrec;
                    if (uStartBit + uNumBits > 128)
                    {
                        Debug.WriteLine("BC7: Invalid block encountered during decoding");
                        Helpers.FillWithErrorColors(data, ref dataIndex, Constants.NUM_PIXELS_PER_BLOCK, DivSize, stride);
                        return(streamIndex);
                    }
                    w1[i] = GetBits(ref uStartBit, uNumBits);
                }

                // read alpha indices
                if (uIndexPrec2 != 0)
                {
                    for (i = 0; i < Constants.NUM_PIXELS_PER_BLOCK; i++)
                    {
                        uint uNumBits = (i != 0 ? uIndexPrec2 : uIndexPrec2 - 1u);
                        if (uStartBit + uNumBits > 128)
                        {
                            Debug.WriteLine("BC7: Invalid block encountered during decoding");
                            Helpers.FillWithErrorColors(data, ref dataIndex, Constants.NUM_PIXELS_PER_BLOCK, DivSize, stride);
                            return(streamIndex);
                        }
                        w2[i] = GetBits(ref uStartBit, uNumBits);
                    }
                }

                for (i = 0; i < Constants.NUM_PIXELS_PER_BLOCK; ++i)
                {
                    byte      uRegion  = Constants.g_aPartitionTable[uPartitions][uShape][i];
                    LDRColorA outPixel = new LDRColorA();
                    if (uIndexPrec2 == 0)
                    {
                        LDRColorA.Interpolate(c[uRegion << 1], c[(uRegion << 1) + 1], w1[i], w1[i], uIndexPrec, uIndexPrec, outPixel);
                    }
                    else
                    {
                        if (uIndexMode == 0)
                        {
                            LDRColorA.Interpolate(c[uRegion << 1], c[(uRegion << 1) + 1], w1[i], w2[i], uIndexPrec, uIndexPrec2, outPixel);
                        }
                        else
                        {
                            LDRColorA.Interpolate(c[uRegion << 1], c[(uRegion << 1) + 1], w2[i], w1[i], uIndexPrec2, uIndexPrec, outPixel);
                        }
                    }

                    switch (uRotation)
                    {
                    case 1: ByteSwap(ref outPixel.r, ref outPixel.a); break;

                    case 2: ByteSwap(ref outPixel.g, ref outPixel.a); break;

                    case 3: ByteSwap(ref outPixel.b, ref outPixel.a); break;
                    }

                    // Note: whether it's sRGB is not taken into consideration
                    // we're returning data that could be either/or depending
                    // on the input BC7 format
                    data[dataIndex++] = outPixel.b;
                    data[dataIndex++] = outPixel.g;
                    data[dataIndex++] = outPixel.r;
                    data[dataIndex++] = outPixel.a;

                    // Is mult 4?
                    if (((i + 1) & 0x3) == 0)
                    {
                        dataIndex += PixelDepthBytes * (stride - DivSize);
                    }
                }
            }
            else
            {
                Debug.WriteLine("BC7: Reserved mode 8 encountered during decoding");
                // Per the BC7 format spec, we must return transparent black
                for (int i = 0; i < Constants.NUM_PIXELS_PER_BLOCK; ++i)
                {
                    data[dataIndex++] = 0;
                    data[dataIndex++] = 0;
                    data[dataIndex++] = 0;
                    data[dataIndex++] = 0;

                    // Is mult 4?
                    if (((i + 1) & 0x3) == 0)
                    {
                        dataIndex += PixelDepthBytes * (stride - DivSize);
                    }
                }
            }

            return(streamIndex);
        }