protected override TextureFormat CreateFrameForGeneralTexture(TacticsOgreEFXTexture texture, int frame, GenericDictionary formatSpecificData, IList <System.Drawing.Image> images, System.Drawing.Image referenceImage, int mipmapsCount) { if (referenceImage != null || images.Count > 1) { throw new TextureFormatException("EFX texture should not contain multiple palettes!"); } TextureFormat segment = null; var image = images.First(); byte entryType = formatSpecificData.Get <byte>(ENTRY_TYPE_KEY); if (entryType != 0x52) { segment = new DummyTexture(string.Format("Data entry, type=0x{0:X}", entryType)); } else { byte bpp = formatSpecificData.Get <byte>(BPP_KEY); segment = new PalettedTextureFormat.Builder() .SetIndexCodec(IndexCodec.FromBitPerPixel(bpp)) .SetImageFilter(new SwizzleFilter(image.Width, image.Height, bpp)) .SetPaletteCodec(ColorCodec.CODEC_32BIT_RGBA) .SetColorComparer(new ARGBColorComparer()) .Build(image); } texture.TextureFormats.Add(segment); return(segment); }
public override void Save(TextureFormat texture, System.IO.Stream outFormatData) { TacticsOgreEFXTexture efxTexture = texture as TacticsOgreEFXTexture; if (efxTexture == null) { throw new TextureFormatException("Not a valid EFX Testure!"); } BinaryWriter writer = new BinaryWriter(new MemoryStream()); writer.Write(magic); writer.Write((byte)0); writer.Write(efxTexture.FormatSpecificData.Get <float>(SCALE_KEY)); writer.Write((uint)0); //temporarily write dummy file size int fileSize = 0x10; foreach (TextureFormat segment in efxTexture.TextureFormats) { byte[] entryData = null; int fullEntrySize = 0; int sizeOfEntryNoHeader1 = 0; byte[] imgData = null, palData = null; PalettedTextureFormat palSegment = segment as PalettedTextureFormat; DummyTexture dummySegment = segment as DummyTexture; if (palSegment != null) { imgData = palSegment.GetImageData(); IList <byte[]> palettes = palSegment.GetPaletteData(); if (palettes.Count > 1) { throw new TextureFormatException("EFX should not support multi palette images!"); } palData = palettes.First(); fullEntrySize = 0x30 + imgData.Length + palData.Length; entryData = imgData.Concat(palData).ToArray(); } else if (dummySegment != null) { entryData = dummySegment.FormatSpecificData.Get <byte[]>(RAW_DATA_KEY); fullEntrySize = 0x10 + entryData.Length; } else { throw new TextureFormatException("EFX segments should be Paletted or dummy!"); } writer.Write(fullEntrySize); writer.Write(segment.FormatSpecificData.Get <ushort>(UNK1_KEY)); writer.Write(segment.FormatSpecificData.Get <ushort>(UNK2_KEY)); sizeOfEntryNoHeader1 = fullEntrySize - 0x10; if (palSegment != null) { writer.Write((uint)sizeOfEntryNoHeader1); } else { writer.Write(segment.FormatSpecificData.Get <uint>(ENTRY_NO_HEADER_KEY)); } writer.Write(segment.FormatSpecificData.Get <ushort>(ID_KEY)); writer.Write(segment.FormatSpecificData.Get <byte>(ENTRY_TYPE_KEY)); writer.Write(segment.FormatSpecificData.Get <byte>(UNK3_KEY)); if (palSegment != null) { byte bpp = segment.FormatSpecificData.Get <byte>(BPP_KEY); writer.Write(bpp); writer.Write(segment.FormatSpecificData.Get <byte>(UNK4_KEY)); writer.Write(segment.FormatSpecificData.Get <ushort>(UNK5_KEY)); writer.Write((ushort)(1 << bpp)); writer.Write((ushort)segment.Width); writer.Write((ushort)segment.Height); writer.Write((ushort)segment.Width); writer.Write((ushort)segment.Height); writer.Write((ushort)0); writer.Write(segment.FormatSpecificData.Get <uint>(UNK6_KEY)); int header2AndImgSize = 0x20 + imgData.Length; writer.Write((uint)header2AndImgSize); writer.Write((uint)sizeOfEntryNoHeader1); writer.Write((uint)0); } writer.Write(entryData); fileSize += fullEntrySize; if (fullEntrySize % 4 != 0) { fileSize = fileSize + 4 - fullEntrySize % 4; writer.Write(Enumerable.Repeat((byte)0, 4 - fullEntrySize % 4).ToArray()); } } writer.BaseStream.Position = 0x0C; writer.Write((uint)fileSize); byte[] finalData = (writer.BaseStream as MemoryStream).ToArray(); outFormatData.Write(finalData, 0, finalData.Length); writer.Close(); }
private TextureFormat ReadEntry(BinaryReader reader) { TextureFormat segment = null; uint fullEntrySize = reader.ReadUInt32(); ushort unk1 = reader.ReadUInt16(); ushort unk2 = reader.ReadUInt16(); uint sizeEntryNotHeader = reader.ReadUInt32(); ushort id = reader.ReadUInt16(); byte entryType = reader.ReadByte(); byte unk3 = reader.ReadByte(); if (entryType != 0x52) // non-image entry { //let's copy the raw data and put it in a dummy texture byte[] buf = reader.ReadBytes((int)fullEntrySize - 0x10); segment = new DummyTexture(string.Format("Data entry, type=0x{0:X}", entryType)); segment.FormatSpecificData.Put <byte[]>(RAW_DATA_KEY, buf); segment.FormatSpecificData.Put <uint>(ENTRY_NO_HEADER_KEY, sizeEntryNotHeader); } else //image data, let's read header 2 data { if (fullEntrySize - sizeEntryNotHeader != 0x10) { throw new TextureFormatException("Not a valid EFX file, full size and size without header 1 do not match!"); } byte bpp = reader.ReadByte(); if (bpp != 4 && bpp != 8) { throw new TextureFormatException("Not a valid EFX file, unsupported bpp=" + bpp); } byte unk4 = reader.ReadByte(); if (unk4 != 0x20) { throw new TextureFormatException("Not a valid EFX file, unk3 not equal to 0x20!"); } ushort unk5 = reader.ReadUInt16(); if (unk5 != 0x01) { throw new TextureFormatException("Not a valid EFX file, unk4 not equal to 0x01!"); } ushort paletteColors = reader.ReadUInt16(); if (paletteColors != 1 << bpp) { throw new TextureFormatException("This EFX file contains more colors then requested by bpp. Is this a multi-palette texture?"); } ushort width = reader.ReadUInt16(); ushort height = reader.ReadUInt16(); if (reader.ReadUInt16() != width) { throw new TextureFormatException("Not a valid EFX file, widths not corresponding!"); } if (reader.ReadUInt16() != height) { throw new TextureFormatException("Not a valid EFX file, widths not corresponding!"); } reader.ReadUInt16(); //pad uint unk6 = reader.ReadUInt32(); if (unk6 != 0x20) { throw new TextureFormatException("Not a valid EFX file, unk5 not equal to 0x20!"); } uint header2AndImgDataSize = reader.ReadUInt32(); uint imgSize = header2AndImgDataSize - 0x20; int paletteSize = paletteColors * 4; if (sizeEntryNotHeader - header2AndImgDataSize != paletteSize) { throw new TextureFormatException("Not a valid EFX file, size of image data not corresponding!"); } if (reader.ReadUInt32() != sizeEntryNotHeader) { throw new TextureFormatException("Not a valid EFX file, size of entry without header 1 not corresponding in header 2!"); } reader.ReadUInt32(); //pad //retrieve image and palette data and construct texture byte[] imgData = reader.ReadBytes((int)imgSize); byte[] palData = reader.ReadBytes(paletteSize); segment = new PalettedTextureFormat.Builder() .SetIndexCodec(IndexCodec.FromBitPerPixel(bpp)) .SetImageFilter(new SwizzleFilter(width, height, bpp)) .SetPaletteCodec(ColorCodec.CODEC_32BIT_RGBA) .SetColorComparer(new ARGBColorComparer()) .Build(imgData, palData, width, height); segment.FormatSpecificData.Put <byte>(BPP_KEY, bpp); segment.FormatSpecificData.Put <byte>(UNK4_KEY, unk4); segment.FormatSpecificData.Put <ushort>(UNK5_KEY, unk5); segment.FormatSpecificData.Put <uint>(UNK6_KEY, unk6); } segment.FormatSpecificData.Put <ushort>(UNK1_KEY, unk1); segment.FormatSpecificData.Put <ushort>(UNK2_KEY, unk2); segment.FormatSpecificData.Put <ushort>(ID_KEY, id); segment.FormatSpecificData.Put <byte>(ENTRY_TYPE_KEY, entryType); segment.FormatSpecificData.Put <byte>(UNK3_KEY, unk3); return(segment); }