private bool Initalize(Bitmap source, GimPaletteFormat paletteFormat, GimDataFormat dataFormat) { // Make sure this bitmap's dimensions are valid if (!HasValidDimensions(source.Width, source.Height)) { return(false); } textureWidth = (ushort)source.Width; textureHeight = (ushort)source.Height; // Set default values hasMetadata = true; metadata = new GimMetadata(); // Set the data format and palette format and load the appropiate codecs this.dataFormat = dataFormat; dataCodec = GimDataCodec.GetDataCodec(dataFormat); // Make sure the data codec exists and we can encode to it if (dataCodec == null || !dataCodec.CanEncode) { return(false); } // Only palettized formats require a pixel codec. if (dataCodec.PaletteEntries != 0) { this.paletteFormat = paletteFormat; pixelCodec = GimPixelCodec.GetPixelCodec(paletteFormat); // Make sure the pixel codec exists and we can encode to it if (pixelCodec == null || !pixelCodec.CanEncode) { return(false); } dataCodec.PixelCodec = pixelCodec; // Convert the bitmap to an array containing indicies. decodedData = BitmapToRawIndexed(source, dataCodec.PaletteEntries, out texturePalette); } else { this.paletteFormat = GimPaletteFormat.Unknown; pixelCodec = null; // Convert the bitmap to an array decodedData = BitmapToRaw(source); } return(true); }
// Decodes a texture private byte[] DecodeTexture() { // Make sure we can decode this texture if (!canDecode) { throw new CannotDecodeTextureException("Cannot decode texture. The palette format and/or data format may not be supported."); } if (paletteOffset != -1) // The texture contains an embedded palette { dataCodec.SetPalette(encodedData, paletteOffset, paletteEntries); } if (swizzled) { return(dataCodec.Decode(GimDataCodec.UnSwizzle(encodedData, dataOffset, textureWidth, textureHeight, dataCodec.Bpp), 0, textureWidth, textureHeight)); } return(dataCodec.Decode(encodedData, dataOffset, textureWidth, textureHeight)); }
private void Initalize() { // Check to see if what we are dealing with is a GIM texture if (!Is(encodedData)) { throw new NotAValidTextureException("This is not a valid GIM texture."); } // Initalize some things paletteFormat = GimPaletteFormat.Unknown; dataFormat = GimDataFormat.Unknown; paletteEntries = 0; paletteOffset = -1; dataOffset = -1; hasMetadata = false; // A GIM is constructed of different chunks. They do not necessarily have to be in order. int eofOffset = -1; int offset = 0x10; int previousOffset = offset; while (offset < encodedData.Length) { // EOF offset chunk if (encodedData[offset] == 0x02) { eofOffset = BitConverter.ToInt32(encodedData, offset + 0x04) + 16; // Go to the next chunk offset += BitConverter.ToInt32(encodedData, offset + 0x08); } // Metadata offset chunk else if (encodedData[offset] == 0x03) { // Skip this chunk. It's not necessary for decoding this texture. offset += BitConverter.ToInt32(encodedData, offset + 0x08); } // Texture data else if (encodedData[offset] == 0x04) { // Get the data format dataFormat = (GimDataFormat)encodedData[offset + 0x14]; // Get the data codec and make sure we can decode using it dataCodec = GimDataCodec.GetDataCodec(dataFormat); // Check to see if the texture data is swizzled swizzled = (BitConverter.ToUInt16(encodedData, offset + 0x16) == 1); // Get the texture's width and height textureWidth = BitConverter.ToUInt16(encodedData, offset + 0x18); textureHeight = BitConverter.ToUInt16(encodedData, offset + 0x1A); // Some textures do not have a width that is a multiple or 16 or a height that is a multiple of 8. // We'll just do it the lazy way and set their width/height to a multiple of 16/8. if (textureWidth % 16 != 0) { textureWidth = (ushort)PTMethods.RoundUp(textureWidth, 16); } if (textureHeight % 8 != 0) { textureHeight = (ushort)PTMethods.RoundUp(textureHeight, 8); } // Set the offset of the texture data dataOffset = offset + 0x50; // Go to the next chunk offset += BitConverter.ToInt32(encodedData, offset + 0x08); } // Palette data else if (encodedData[offset] == 0x05) { // Get the palette format paletteFormat = (GimPaletteFormat)encodedData[offset + 0x14]; // Get the pixel codec and make sure we can decode using it pixelCodec = GimPixelCodec.GetPixelCodec(paletteFormat); // Get the number of entries in the palette paletteEntries = BitConverter.ToUInt16(encodedData, offset + 0x18); // Set the offset of the palette data paletteOffset = offset + 0x50; // Go to the next chunk offset += BitConverter.ToInt32(encodedData, offset + 0x08); } // Metadata chunk else if (encodedData[offset] == 0xFF) { // Read in some metadata hasMetadata = true; metadata = new GimMetadata(); int metadataOffset = 0x10; metadata.OriginalFilename = PTMethods.StringFromBytes(encodedData, offset + metadataOffset); metadataOffset += metadata.OriginalFilename.Length + 1; metadata.User = PTMethods.StringFromBytes(encodedData, offset + metadataOffset); metadataOffset += metadata.User.Length + 1; metadata.Timestamp = PTMethods.StringFromBytes(encodedData, offset + metadataOffset); metadataOffset += metadata.Timestamp.Length + 1; metadata.Program = PTMethods.StringFromBytes(encodedData, offset + metadataOffset); metadataOffset += metadata.Program.Length + 1; // Go to the next chunk offset += BitConverter.ToInt32(encodedData, offset + 0x08); } // Invalid chunk else { return; } // Make sure we are actually advancing in the file, so we don't end up reaching a negative offset // or ending up in an infinite loop if (offset <= previousOffset) { return; } previousOffset = offset; } // If all went well, offset should be equal to eofOffset if (offset != eofOffset) { return; } // If this is a non-palettized format, make sure we have a data codec if (dataCodec != null && dataCodec.PaletteEntries == 0) { canDecode = true; } // If this is a palettized format, make sure we have a palette codec, a data codec, // and that the number of palette entires is less than or equal to what this data format supports if (dataCodec != null && dataCodec.PaletteEntries != 0 && pixelCodec != null && paletteEntries <= dataCodec.PaletteEntries) { // Set the data format's pixel codec dataCodec.PixelCodec = pixelCodec; canDecode = true; } initalized = true; }
private bool Initalize(Bitmap source, GimPaletteFormat paletteFormat, GimDataFormat dataFormat) { // Make sure this bitmap's dimensions are valid if (!HasValidDimensions(source.Width, source.Height)) return false; textureWidth = (ushort)source.Width; textureHeight = (ushort)source.Height; // Set default values hasMetadata = true; metadata = new GimMetadata(); // Set the data format and palette format and load the appropiate codecs this.dataFormat = dataFormat; dataCodec = GimDataCodec.GetDataCodec(dataFormat); // Make sure the data codec exists and we can encode to it if (dataCodec == null || !dataCodec.CanEncode) return false; // Only palettized formats require a pixel codec. if (dataCodec.PaletteEntries != 0) { this.paletteFormat = paletteFormat; pixelCodec = GimPixelCodec.GetPixelCodec(paletteFormat); // Make sure the pixel codec exists and we can encode to it if (pixelCodec == null || !pixelCodec.CanEncode) return false; dataCodec.PixelCodec = pixelCodec; // Convert the bitmap to an array containing indicies. decodedData = BitmapToRawIndexed(source, dataCodec.PaletteEntries, out texturePalette); } else { this.paletteFormat = GimPaletteFormat.Unknown; pixelCodec = null; // Convert the bitmap to an array decodedData = BitmapToRaw(source); } return true; }
// Encodes a texture private MemoryStream EncodeTexture() { // Get the lengths of the various chunks int eofOffsetChunkLength = 16, metadataOffsetChunkLength = 16, paletteDataChunkLength = 0, textureDataChunkLength = 0, metadataChunkLength = 0; if (dataCodec.PaletteEntries != 0) { paletteDataChunkLength = 80 + (dataCodec.PaletteEntries * (pixelCodec.Bpp >> 3)); } textureDataChunkLength = 80 + ((textureWidth * textureHeight * dataCodec.Bpp) >> 3); if (hasMetadata) { metadataChunkLength = 16; if (metadata.OriginalFilename != null) { metadataChunkLength += metadata.OriginalFilename.Length; } metadataChunkLength++; if (metadata.User != null) { metadataChunkLength += metadata.User.Length; } metadataChunkLength++; if (metadata.Timestamp != null) { metadataChunkLength += metadata.Timestamp.Length; } metadataChunkLength++; if (metadata.Program != null) { metadataChunkLength += metadata.Program.Length; } metadataChunkLength++; } // Calculate what the length of the texture will be int textureLength = 16 + eofOffsetChunkLength + metadataOffsetChunkLength + paletteDataChunkLength + textureDataChunkLength + metadataChunkLength; MemoryStream destination = new MemoryStream(textureLength); // Write the GIM header PTStream.WriteCString(destination, "MIG.00.1PSP", 12); PTStream.WriteUInt32(destination, 0); // Write the EOF offset chunk PTStream.WriteUInt16(destination, 0x02); PTStream.WriteUInt16(destination, 0); PTStream.WriteInt32(destination, textureLength - 16); PTStream.WriteInt32(destination, eofOffsetChunkLength); PTStream.WriteUInt32(destination, 16); // Write the metadata offset chunk PTStream.WriteUInt16(destination, 0x03); PTStream.WriteUInt16(destination, 0); if (hasMetadata) { PTStream.WriteInt32(destination, textureLength - metadataChunkLength - 32); } else { PTStream.WriteInt32(destination, textureLength - 32); } PTStream.WriteInt32(destination, metadataOffsetChunkLength); PTStream.WriteUInt32(destination, 16); // Write the palette data, if we have a palette if (dataCodec.PaletteEntries != 0) { PTStream.WriteUInt16(destination, 0x05); PTStream.WriteUInt16(destination, 0); PTStream.WriteInt32(destination, paletteDataChunkLength); PTStream.WriteInt32(destination, paletteDataChunkLength); PTStream.WriteUInt32(destination, 16); PTStream.WriteUInt16(destination, 48); PTStream.WriteUInt16(destination, 0); PTStream.WriteUInt16(destination, (byte)paletteFormat); PTStream.WriteUInt16(destination, 0); PTStream.WriteUInt16(destination, (ushort)dataCodec.PaletteEntries); destination.Write(new byte[] { 0x01, 0x00, 0x20, 0x00, 0x10, 0x00 }, 0, 6); destination.Write(new byte[] { 0x01, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00 }, 0, 8); PTStream.WriteUInt32(destination, 0x30); PTStream.WriteUInt32(destination, 0x40); PTStream.WriteInt32(destination, paletteDataChunkLength - 16); PTStream.WriteUInt32(destination, 0); destination.Write(new byte[] { 0x02, 0x00, 0x01, 0x00, 0x03, 0x00, 0x01, 0x00 }, 0, 8); destination.Write(new byte[] { 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, 0, 16); byte[] palette = pixelCodec.EncodePalette(texturePalette, dataCodec.PaletteEntries); destination.Write(palette, 0, palette.Length); } // Write the texture data PTStream.WriteUInt16(destination, 0x04); PTStream.WriteUInt16(destination, 0); PTStream.WriteInt32(destination, textureDataChunkLength); PTStream.WriteInt32(destination, textureDataChunkLength); PTStream.WriteUInt32(destination, 16); PTStream.WriteUInt16(destination, 48); PTStream.WriteUInt16(destination, 0); PTStream.WriteUInt16(destination, (byte)dataFormat); PTStream.WriteUInt16(destination, 1); // Always swizzled PTStream.WriteUInt16(destination, textureWidth); PTStream.WriteUInt16(destination, textureHeight); if (dataCodec.PaletteEntries != 0) { // For palettized textures, this is the bpp for this data format PTStream.WriteUInt16(destination, (ushort)dataCodec.Bpp); } else { // For non-palettized textures, this is always specified as 32bpp PTStream.WriteUInt16(destination, 32); } PTStream.WriteUInt16(destination, 16); destination.Write(new byte[] { 0x08, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x30, 0x00, 0x00, 0x00, 0x40, 0x00, 0x00, 0x00 }, 0, 16); PTStream.WriteInt32(destination, textureDataChunkLength - 16); PTStream.WriteUInt32(destination, 0); destination.Write(new byte[] { 0x01, 0x00, 0x01, 0x00, 0x03, 0x00, 0x01, 0x00 }, 0, 8); destination.Write(new byte[] { 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, 0, 16); byte[] textureData = GimDataCodec.Swizzle(dataCodec.Encode(decodedData, 0, textureWidth, textureHeight), 0, textureWidth, textureHeight, dataCodec.Bpp); destination.Write(textureData, 0, textureData.Length); // Write the metadata, only if we are including it if (hasMetadata) { PTStream.WriteUInt16(destination, 0xFF); PTStream.WriteUInt16(destination, 0); PTStream.WriteInt32(destination, metadataChunkLength); PTStream.WriteInt32(destination, metadataChunkLength); PTStream.WriteUInt32(destination, 16); PTStream.WriteCString(destination, metadata.OriginalFilename); PTStream.WriteCString(destination, metadata.User); PTStream.WriteCString(destination, metadata.Timestamp); PTStream.WriteCString(destination, metadata.Program); } return(destination); }