Пример #1
0
            public override void DecodePixel(byte[] source, int sourceIndex, byte[] destination, int destinationIndex)
            {
                ushort pixel = PTMethods.ToUInt16(source, sourceIndex, true);

                destination[destinationIndex + 3] = (byte)(((pixel >> 12) & 0x0F) * 0xFF / 0x0F);
                destination[destinationIndex + 2] = (byte)(((pixel >> 8) & 0x0F) * 0xFF / 0x0F);
                destination[destinationIndex + 1] = (byte)(((pixel >> 4) & 0x0F) * 0xFF / 0x0F);
                destination[destinationIndex + 0] = (byte)(((pixel >> 0) & 0x0F) * 0xFF / 0x0F);
            }
Пример #2
0
        protected override bool Initalize()
        {
            // Check to see if what we are dealing with is a GVP palette
            if (!Is(encodedData))
            {
                return(false);
            }

            // Get the pixel format and the codec and make sure we can decode using them
            pixelFormat = (PvrPixelFormat)encodedData[0x08];
            pixelCodec  = PvrPixelCodec.GetPixelCodec(pixelFormat);
            if (pixelCodec == null)
            {
                return(false);
            }

            // Get the number of colors contained in the palette
            paletteEntries = PTMethods.ToUInt16(encodedData, 0x0E, true);

            return(true);
        }
Пример #3
0
        protected override void Initalize()
        {
            // Check to see if what we are dealing with is a PVR texture
            if (!Is(encodedData))
            {
                throw new NotAValidTextureException("This is not a valid PVR texture.");
            }

            // Determine the offsets of the GBIX (if present) and PVRT header chunks.
            if (PTMethods.Contains(encodedData, 0x00, gbixFourCC))
            {
                gbixOffset = 0x00;
                pvrtOffset = 0x08 + PTMethods.ToInt32(encodedData, gbixOffset + 4, true);
            }
            else if (PTMethods.Contains(encodedData, 0x04, gbixFourCC))
            {
                gbixOffset = 0x04;
                pvrtOffset = 0x0C + PTMethods.ToInt32(encodedData, gbixOffset + 4, true);
            }
            else if (PTMethods.Contains(encodedData, 0x04, pvrtFourCC))
            {
                gbixOffset = -1;
                pvrtOffset = 0x04;
            }
            else
            {
                gbixOffset = -1;
                pvrtOffset = 0x00;
            }

            // Read the global index (if it is present). If it is not present, just set it to 0.
            if (gbixOffset != -1)
            {
                globalIndex = PTMethods.ToUInt32(encodedData, gbixOffset + 0x08, true);
            }
            else
            {
                globalIndex = 0;
            }

            // Read information about the texture
            textureWidth  = PTMethods.ToUInt16(encodedData, pvrtOffset + 0x0C, true);
            textureHeight = PTMethods.ToUInt16(encodedData, pvrtOffset + 0x0E, true);

            pixelFormat = (PvrPixelFormat)encodedData[pvrtOffset + 0x08];
            dataFormat  = (PvrDataFormat)encodedData[pvrtOffset + 0x09];

            // Get the codecs and make sure we can decode using them
            pixelCodec = PvrPixelCodec.GetPixelCodec(pixelFormat);
            dataCodec  = PvrDataCodec.GetDataCodec(dataFormat);

            if (dataCodec != null && pixelCodec != null)
            {
                dataCodec.PixelCodec = pixelCodec;
                canDecode            = true;
            }

            // Set the number of palette entries
            // The number in a Small Vq encoded texture various based on its size
            paletteEntries = dataCodec.PaletteEntries;
            if (dataFormat == PvrDataFormat.SmallVq || dataFormat == PvrDataFormat.SmallVqMipmaps)
            {
                if (textureWidth <= 16)
                {
                    paletteEntries = 64; // Actually 16
                }
                else if (textureWidth <= 32)
                {
                    paletteEntries = 256; // Actually 64
                }
                else if (textureWidth <= 64)
                {
                    paletteEntries = 512; // Actually 128
                }
                else
                {
                    paletteEntries = 1024; // Actually 256
                }
            }

            // Set the palette and data offsets
            if (!canDecode || paletteEntries == 0 || dataCodec.NeedsExternalPalette)
            {
                paletteOffset = -1;
                dataOffset    = pvrtOffset + 0x10;
            }
            else
            {
                paletteOffset = pvrtOffset + 0x10;
                dataOffset    = paletteOffset + (paletteEntries * (pixelCodec.Bpp >> 3));
            }

            // Get the compression format and determine if we need to decompress this texture
            compressionFormat = GetCompressionFormat(encodedData, pvrtOffset, dataOffset);
            compressionCodec  = PvrCompressionCodec.GetCompressionCodec(compressionFormat);

            if (compressionFormat != PvrCompressionFormat.None && compressionCodec != null)
            {
                encodedData = compressionCodec.Decompress(encodedData, dataOffset, pixelCodec, dataCodec);

                // Now place the offsets in the appropiate area
                if (compressionFormat == PvrCompressionFormat.Rle)
                {
                    if (gbixOffset != -1)
                    {
                        gbixOffset -= 4;
                    }
                    pvrtOffset -= 4;
                    if (paletteOffset != -1)
                    {
                        paletteOffset -= 4;
                    }
                    dataOffset -= 4;
                }
            }

            // If the texture contains mipmaps, gets the offsets of them
            if (canDecode && dataCodec.HasMipmaps)
            {
                mipmapOffsets = new int[(int)Math.Log(textureWidth, 2) + 1];

                int mipmapOffset = 0;

                // Calculate the padding for the first mipmap offset
                if (dataFormat == PvrDataFormat.SquareTwiddledMipmaps)
                {
                    // A 1x1 mipmap takes up as much space as a 2x1 mipmap
                    mipmapOffset = (dataCodec.Bpp) >> 3;
                }
                else if (dataFormat == PvrDataFormat.SquareTwiddledMipmapsAlt)
                {
                    // A 1x1 mipmap takes up as much space as a 2x2 mipmap
                    mipmapOffset = (3 * dataCodec.Bpp) >> 3;
                }

                for (int i = mipmapOffsets.Length - 1, size = 1; i >= 0; i--, size <<= 1)
                {
                    mipmapOffsets[i] = mipmapOffset;

                    mipmapOffset += Math.Max((size * size * dataCodec.Bpp) >> 3, 1);
                }
            }

            initalized = true;
        }