/// <summary> /// Opens a texture to encode from a stream. /// </summary> /// <param name="source">Stream that contains the texture data.</param> /// <param name="length">Number of bytes to read.</param> /// <param name="pixelFormat">Pixel format to encode the texture to.</param> /// <param name="dataFormat">Data format to encode the texture to.</param> public GimTextureEncoder(Stream source, int length, GimPaletteFormat paletteFormat, GimDataFormat dataFormat) { MemoryStream buffer = new MemoryStream(); PTStream.CopyPartTo(source, buffer, length); initalized = Initalize(new Bitmap(buffer), paletteFormat, dataFormat); }
/// <summary> /// Saves the encoded texture to the specified stream. /// </summary> /// <param name="destination">The stream to save the texture to.</param> public void Save(Stream destination) { if (!initalized) { throw new TextureNotInitalizedException("Cannot encode this texture as it is not initalized."); } MemoryStream textureStream = EncodeTexture(); textureStream.Position = 0; PTStream.CopyTo(textureStream, destination); }
/// <summary> /// Saves the encoded texture to the specified path. /// </summary> /// <param name="path">Name of the file to save the data to.</param> public void Save(string path) { if (!initalized) { throw new TextureNotInitalizedException("Cannot encode this texture as it is not initalized."); } using (FileStream destination = File.Create(path)) { MemoryStream textureStream = EncodeTexture(); textureStream.Position = 0; PTStream.CopyTo(textureStream, destination); } }
// 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); }