public TextureLumpInfo(TextureByteIndexPaletteWithMipmaps texture) { if (texture.Name.Length > NameLength - 1) { throw new ArgumentOutOfRangeException("texture"); } char[] name = new char[NameLength]; for (int i = 0; i < texture.Name.Length; i++) { name[i] = texture.Name[i]; } this.Width = (uint)texture.Width; this.Height = (uint)texture.Height; this.MipmapOffsets = new uint[MipmapOffsetsLength]; }
/// <summary> /// Load texture (with mipmaps) of this TextureLumpInfo. /// </summary> /// <param name="reader">Source stream.</param> /// <param name="texture_offset">Offset of this TextureLumpInfo in source stream.</param> public TextureByteIndexPaletteWithMipmaps LoadTexture(BinaryReader reader, long texture_offset = 0) { reader.BaseStream.Position = texture_offset + this.MipmapOffsets[0]; // Indices to main texture (mipmap[0]) byte[] indices = reader.ReadBytes((int)(this.Width * this.Height)); // Loading color palette (after last mipmap) int last_mipmap_index = this.MipmapOffsets.Length - 1; reader.BaseStream.Position = (long)texture_offset + this.MipmapOffsets[last_mipmap_index] + ((this.Width / (int)Math.Pow(2, last_mipmap_index)) * (this.Height / (int)Math.Pow(2, last_mipmap_index))) + 2; Color[] palette = new Color[256]; for (int p = 0; p < palette.Length; p++) { byte r = reader.ReadByte(); byte g = reader.ReadByte(); byte b = reader.ReadByte(); palette[p] = new Color(r / 255f, g / 255f, b / 255f); } // Last index is transparent if (palette[255].r == 0 && palette[255].g == 0 && palette[255].b == 1f) { palette[255] = new Color(0, 0, 0, 0); } // Texture instance (with main texture and color palette) var texture = new TextureByteIndexPaletteWithMipmaps(this.Name_s, (int)this.Width, (int)this.Height, indices, palette); // Adding mipmaps to texture instance // mipmap[1] is first mipmap (0 is main texture) // Each mipmap has half dimensions then previous one for (int mipmap_level = 1; mipmap_level < this.MipmapOffsets.Length; mipmap_level++) { reader.BaseStream.Position = (long)texture_offset + this.MipmapOffsets[mipmap_level]; int width = (int)(this.Width / Math.Pow(2, mipmap_level)); int height = (int)(this.Height / Math.Pow(2, mipmap_level)); texture.AddMipmap(mipmap_level, reader.ReadBytes(width * height)); } return(texture); }
/// <summary> /// Save texture data. /// This should be run after saving the TextureLumpInfo /// </summary> /// <param name="writer">Output stream.</param> /// <param name="texture">Texture to save. Only transparent color can be palette[255] and must be R=0,G=0,B=255.</param> public static void SaveTexture(BinaryWriter writer, TextureByteIndexPaletteWithMipmaps texture) { // All MipMaps (including main texture) for (int m = 0; m < TextureLumpInfo.MipmapOffsetsLength; m++) { writer.Write(texture.GetMipmap(m)); writer.Flush(); } writer.Write((ushort)0);//2 dummy bytes writer.Flush(); // Color palette { // Used colors in palette for (int p = 0; p < texture.Palette.Length; p++) { var c = texture.Palette[p]; writer.Write((byte)(c.r * 255)); //R writer.Write((byte)(c.g * 255)); //G writer.Write((byte)(c.b * 255)); //B } // Unused colors in palette for (int p = texture.Palette.Length; p < 255; p++) { writer.Write(0); //R writer.Write(0); //G writer.Write(0); //B } // Transparent blue if unused if (texture.Palette.Length < 255) { // Index: 255 writer.Write(0); //R writer.Write(0); //G writer.Write(255); //B } } writer.Flush(); }