Exemplo n.º 1
0
        /// <summary>
        /// Given a block, extract the colour information and convert to 5554 formats
        /// </summary>
        private unsafe static void Unpack5554Colour(AmtcBlock *block, int *abColors)
        {
            uint *rawBits = stackalloc uint[2];

            // extract A and B
            // 15 bits (shifted up by one)
            rawBits[0] = block->PackedData1 & (0xFFFE);
            // 16 bits
            rawBits[1] = block->PackedData1 >> 16;

            // step through both colours
            for (int i = 0; i < 2; i++)
            {
                // if completely opaque
                if ((rawBits[i] & (1 << 15)) != 0)
                {
                    // extract R and G (both 5 bit)
                    abColors[i * 4 + 0] = (int)((rawBits[i] >> 10) & 0x1F);
                    abColors[i * 4 + 1] = (int)((rawBits[i] >> 5) & 0x1F);

                    // The precision of Blue depends on  A or B. If A then we need to replicate the top bit to get 5 bits in total
                    abColors[i * 4 + 2] = (int)(rawBits[i] & 0x1F);
                    if (i == 0)
                    {
                        abColors[0 * 4 + 2] |= abColors[0 * 4 + 2] >> 4;
                    }

                    // set 4bit alpha fully on...
                    abColors[i * 4 + 3] = 0xF;
                }
                // else if colour has variable translucency
                else
                {
                    // extract R and G (both 4 bit). Leave a space on the end for the replication of bits
                    abColors[i * 4 + 0] = (int)((rawBits[i] >> (8 - 1)) & 0x1E);
                    abColors[i * 4 + 1] = (int)((rawBits[i] >> (4 - 1)) & 0x1E);

                    // replicate bits to truly expand to 5 bits
                    abColors[i * 4 + 0] |= abColors[i * 4 + 0] >> 4;
                    abColors[i * 4 + 1] |= abColors[i * 4 + 1] >> 4;

                    // grab the 3(+padding) or 4 bits of blue and add an extra padding bit
                    abColors[i * 4 + 2] = (int)((rawBits[i] & 0xF) << 1);

                    // expand from 3 to 5 bits if this is from colour A, or 4 to 5 bits if from colour B
                    if (i == 0)
                    {
                        abColors[0 * 4 + 2] |= abColors[0 * 4 + 2] >> 3;
                    }
                    else
                    {
                        abColors[0 * 4 + 2] |= abColors[0 * 4 + 2] >> 4;
                    }

                    // set the alpha bits to be 3 + a zero on the end
                    abColors[i * 4 + 3] = (int)((rawBits[i] >> 11) & 0xE);
                }
            }
        }
Exemplo n.º 2
0
        private unsafe static void PVRDecompress(byte *compressedData, bool do2bitMode, int xDim, int yDim, byte[] output)
        {
            int xBlockSize = do2bitMode ? BlockX2bpp : BlockX4bpp;
            // for MBX don't allow the sizes to get too small
            int blockXDim = Math.Max(2, xDim / xBlockSize);
            int blockYDim = Math.Max(2, yDim / BlockYSize);

            uint pblocki00 = uint.MaxValue;
            uint pblocki01 = uint.MaxValue;
            uint pblocki10 = uint.MaxValue;
            uint pblocki11 = uint.MaxValue;

            Colours5554 *m_colors = stackalloc Colours5554[2 * 2];
            // interpolated A colors for the pixel
            int *aSig = stackalloc int[4];
            // interpolated B colors for the pixel
            int *bSig            = stackalloc int[4];
            int *modulationVals  = stackalloc int[8 * 16];
            int *modulationModes = stackalloc int[8 * 16];

            // step through the pixels of the image decompressing each one in turn.
            // Note that this is a hideously inefficient way to do this!
            for (int y = 0; y < yDim; y++)
            {
                for (int x = 0; x < xDim; x++)
                {
                    // map this pixel to the top left neighbourhood of blocks
                    int blockX = (x - xBlockSize / 2);
                    int blockY = (y - BlockYSize / 2);

                    blockX = LimitCoord(blockX, xDim) / xBlockSize;
                    blockY = LimitCoord(blockY, yDim) / BlockYSize;

                    // compute the positions of the other 3 blocks
                    int blockXp1 = LimitCoord(blockX + 1, blockXDim);
                    int blockYp1 = LimitCoord(blockY + 1, blockYDim);

                    // map to block memory locations
                    uint blocki00 = TwiddleUV((uint)blockYDim, (uint)blockXDim, (uint)blockY, (uint)blockX);
                    uint blocki01 = TwiddleUV((uint)blockYDim, (uint)blockXDim, (uint)blockY, (uint)blockXp1);
                    uint blocki10 = TwiddleUV((uint)blockYDim, (uint)blockXDim, (uint)blockYp1, (uint)blockX);
                    uint blocki11 = TwiddleUV((uint)blockYDim, (uint)blockXDim, (uint)blockYp1, (uint)blockXp1);

                    // extract the colours and the modulation information IF the previous values have changed.
                    bool changed = blocki00 != pblocki00 || blocki01 != pblocki01 || blocki10 != pblocki10 || blocki11 != pblocki11;
                    if (changed)
                    {
                        AmtcBlock *block00 = &((AmtcBlock *)compressedData)[blocki00];
                        Unpack5554Colour(block00, m_colors[0].Reps);
                        UnpackModulations(block00, do2bitMode, modulationVals, modulationModes, 0, 0);
                        AmtcBlock *block01 = &((AmtcBlock *)compressedData)[blocki01];
                        Unpack5554Colour(block01, m_colors[1].Reps);
                        UnpackModulations(block01, do2bitMode, modulationVals, modulationModes, xBlockSize, 0);
                        AmtcBlock *block10 = &((AmtcBlock *)compressedData)[blocki10];
                        Unpack5554Colour(block10, m_colors[2].Reps);
                        UnpackModulations(block10, do2bitMode, modulationVals, modulationModes, 0, BlockYSize);
                        AmtcBlock *block11 = &((AmtcBlock *)compressedData)[blocki11];
                        Unpack5554Colour(block11, m_colors[3].Reps);
                        UnpackModulations(block11, do2bitMode, modulationVals, modulationModes, xBlockSize, BlockYSize);

                        pblocki00 = blocki00;
                        pblocki01 = blocki01;
                        pblocki10 = blocki10;
                        pblocki11 = blocki11;
                    }

                    // decompress the pixel.  First compute the interpolated A and B signals
                    InterpolateColours(m_colors[0].Reps, m_colors[1].Reps, m_colors[2].Reps, m_colors[3].Reps, 0, do2bitMode, x, y, aSig);
                    InterpolateColours(m_colors[0].Reps, m_colors[1].Reps, m_colors[2].Reps, m_colors[3].Reps, 1, do2bitMode, x, y, bSig);
                    GetModulationValue(x, y, do2bitMode, modulationVals, modulationModes, out int mod, out bool doPT);

                    // compute the modulated color. Swap red and blue channel
                    int position = (x + y * xDim) << 2;
                    output[position + 0] = (byte)((aSig[2] * 8 + mod * (bSig[2] - aSig[2])) >> 3);
                    output[position + 1] = (byte)((aSig[1] * 8 + mod * (bSig[1] - aSig[1])) >> 3);
                    output[position + 2] = (byte)((aSig[0] * 8 + mod * (bSig[0] - aSig[0])) >> 3);
                    output[position + 3] = doPT ? (byte)0 : (byte)((aSig[3] * 8 + mod * (bSig[3] - aSig[3])) >> 3);
                }
            }
        }
Exemplo n.º 3
0
        /// <summary>
        /// Given the block and the texture type and it's relative position in the 2x2 group of blocks, extract the bit patterns for the fully defined pixels.
        /// </summary>
        private unsafe static void UnpackModulations(AmtcBlock *block, bool do2bitMode, int *modulationVals, int *modulationModes, int startX, int startY)
        {
            int  blockModMode   = (int)(block->PackedData1 & 1);
            uint modulationBits = block->PackedData0;

            // if it's in an interpolated mode
            if (do2bitMode && (blockModMode != 0))
            {
                // run through all the pixels in the block. Note we can now treat all the "stored" values as if they have 2bits (even when they didn't!)
                for (int y = 0; y < BlockYSize; y++)
                {
                    for (int x = 0; x < BlockX2bpp; x++)
                    {
                        modulationModes[(y + startY) * 16 + x + startX] = blockModMode;

                        // if this is a stored value...
                        if (((x ^ y) & 1) == 0)
                        {
                            modulationVals[(y + startY) * 16 + x + startX] = (int)(modulationBits & 3);
                            modulationBits >>= 2;
                        }
                    }
                }
            }
            // else if direct encoded 2bit mode - i.e. 1 mode bit per pixel
            else if (do2bitMode)
            {
                for (int y = 0; y < BlockYSize; y++)
                {
                    for (int x = 0; x < BlockX2bpp; x++)
                    {
                        modulationModes[(y + startY) * 16 + x + startX] = blockModMode;

                        // double the bits so 0=> 00, and 1=>11
                        if ((modulationBits & 1) != 0)
                        {
                            modulationVals[(y + startY) * 16 + x + startX] = 0x3;
                        }
                        else
                        {
                            modulationVals[(y + startY) * 16 + x + startX] = 0x0;
                        }
                        modulationBits >>= 1;
                    }
                }
            }
            // else its the 4bpp mode so each value has 2 bits
            else
            {
                for (int y = 0; y < BlockYSize; y++)
                {
                    for (int x = 0; x < BlockX4bpp; x++)
                    {
                        modulationModes[(y + startY) * 16 + x + startX] = blockModMode;

                        modulationVals[(y + startY) * 16 + x + startX] = (int)(modulationBits & 3);
                        modulationBits >>= 2;
                    }
                }
            }

            // make sure nothing is left over
            if (modulationBits != 0)
            {
                throw new Exception("Something is left over");
            }
        }