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); }
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); }
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; }