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); }
protected override TextureFormat CreateFrameForGeneralTexture(NamcoTexture texture, int frame, GenericDictionary formatSpecificData, IList <System.Drawing.Image> images, System.Drawing.Image referenceImage, int mipmapsCount) { TextureFormat segment = null; ushort version = texture.FormatSpecificData.Get <ushort>(VERSION_KEY); byte clutFormat = formatSpecificData.Get <byte>(CLUTFORMAT_KEY); byte depth = formatSpecificData.Get <byte>(DEPTH_KEY); int colorsCount = 1 << depth; int width = images.First().Width; int height = images.First().Height; byte[] data = formatSpecificData.Get <byte[]>(DATA_KEY); byte[] userData = formatSpecificData.Get <byte[]>(USERDATA_KEY); if (IsPaletted(clutFormat)) { ColorCodec paletteCodec; IndexCodec indexCodec; ImageFilter imgFilter; PaletteFilter palFilter; GetPalettedTools(version, clutFormat, depth, colorsCount, width, height, data, userData, out paletteCodec, out indexCodec, out imgFilter, out palFilter); var builder = new PalettedTextureFormat.Builder() .SetPaletteCodec(paletteCodec) .SetMipmapsCount(mipmapsCount) .SetIndexCodec(indexCodec) .SetImageFilter(imgFilter) .SetPaletteFilter(palFilter); if (referenceImage != null) { segment = builder.Build(referenceImage, images.Select(img => img.GetColorArray()).ToList()); } else { segment = builder.Build(images.First()); } } else { ColorCodec imageCodec; ImageFilter imgFilter; GetUnpalettedTools(version, clutFormat, depth, colorsCount, width, height, data, userData, out imageCodec, out imgFilter); segment = new GenericTextureFormat.Builder() .SetColorCodec(imageCodec) .SetMipmapsCount(mipmapsCount) .SetImageFilter(imgFilter) .Build(images.First()); } texture.TextureFormats.Add(segment); return(segment); }
public TextureFormat Open(System.IO.Stream formatData) { BinaryReader reader = new BinaryReader(formatData); try { char[] magic = reader.ReadChars(MAGIC.Length); if (new string(magic) != MAGIC) { throw new TextureFormatException("Not a valid TX48 Texture!"); } int bpp = reader.ReadInt32(); if (bpp != 0 && bpp != 1) { throw new TextureFormatException("Illegal Bit per pixel value!"); } bpp = (bpp + 1) * 4; int width = reader.ReadInt32(); int height = reader.ReadInt32(); int paletteOffset = reader.ReadInt32(); if (paletteOffset != 0x40) { throw new TextureFormatException("TX48 Header is wrong!"); } int paletteSize = reader.ReadInt32(); int imageOffset = reader.ReadInt32(); int imageSize = reader.ReadInt32(); reader.BaseStream.Position += 0x20; byte[] paletteData = reader.ReadBytes(paletteSize); byte[] imageData = reader.ReadBytes(imageSize); PalettedTextureFormat.Builder builder = new PalettedTextureFormat.Builder(); builder.SetPaletteCodec(ColorCodec.CODEC_32BIT_RGBA) .SetIndexCodec(IndexCodec.FromBitPerPixel(bpp)); PalettedTextureFormat segment = builder.Build(imageData, paletteData, width, height); TX48Texture texture = new TX48Texture(); texture.TextureFormats.Add(segment); return(texture); } catch (Exception e) { if (e is TextureFormatException) { throw; } throw new TextureFormatException(e.Message, e); } }
public TextureFormat Import(MetadataReader metadata, string directory) { metadata.EnterSection("TX48Texture"); string basename = metadata.GetAttribute <string>("Basename"); metadata.EnterSection("TX48Segment"); int bpp = metadata.Get <int>("Bpp"); Image img = Image.FromFile(Path.Combine(directory, basename + ".png")); metadata.ExitSection(); metadata.ExitSection(); PalettedTextureFormat segment = new PalettedTextureFormat.Builder() .SetPaletteCodec(ColorCodec.CODEC_32BIT_RGBA) .SetIndexCodec(IndexCodec.FromBitPerPixel(bpp)) .Build(img); TX48Texture texture = new TX48Texture(); texture.TextureFormats.Add(segment); return(texture); }
private TextureFormat ConstructSegment(BinaryReader reader, ushort version) { ByteOrder order = GetByteOrder(); uint totalSize = reader.ReadUInt32(order); uint paletteSize = reader.ReadUInt32(order); uint imageSize = reader.ReadUInt32(order); uint headerSize = reader.ReadUInt16(order); int colorsCount = reader.ReadUInt16(order); byte format = reader.ReadByte(); byte mipmapsCount = reader.ReadByte(); if (!IsSupportedFormat(format)) { throw new TextureFormatException("Unsupported image format!"); } byte clutFormat = reader.ReadByte(); byte depth = reader.ReadByte(); int width = reader.ReadUInt16(order); int height = reader.ReadUInt16(order); byte[] data = reader.ReadBytes(24); uint userDataSize = headerSize - 0x30; byte[] userdata = null; if (userDataSize > 0) { userdata = reader.ReadBytes((int)userDataSize); } int totalPixels = 0; for (int i = 0; i < mipmapsCount; i++) { totalPixels += ImageUtils.GetMipmapWidth(width, i) * ImageUtils.GetMipmapHeight(height, i); } int firstImageSize = mipmapsCount != 0? (int)((width * height * imageSize) / totalPixels) : 0; byte[] imgData = reader.ReadBytes(firstImageSize); //we don't need to load the mipmaps, since they can be generated as needed. //just skip the mipmaps reader.BaseStream.Position += (imageSize - firstImageSize); byte[] palData = reader.ReadBytes((int)paletteSize); TextureFormat segment = null; if (IsPaletted(clutFormat)) { int colorSize = GetPaletteColorSize(clutFormat); int numberOfPalettes = palData.Length / (colorsCount * colorSize); int singlePaletteSize = palData.Length / numberOfPalettes; IList <byte[]> palettes = new List <byte[]>(numberOfPalettes); for (int i = 0; i < numberOfPalettes; i++) { palettes.Add(palData.Skip(i * singlePaletteSize).Take(singlePaletteSize).ToArray()); } PalettedTextureFormat.Builder builder = new PalettedTextureFormat.Builder(); ColorCodec paletteCodec; IndexCodec indexCodec; ImageFilter imgFilter; PaletteFilter palFilter; GetPalettedTools(version, clutFormat, depth, colorsCount, width, height, data, userdata, out paletteCodec, out indexCodec, out imgFilter, out palFilter); builder.SetPaletteCodec(paletteCodec) .SetMipmapsCount(mipmapsCount) .SetIndexCodec(indexCodec) .SetImageFilter(imgFilter) .SetPaletteFilter(palFilter); segment = builder.Build(imgData, palettes, width, height); } else { ColorCodec imageCodec; ImageFilter imgFilter; GenericTextureFormat.Builder builder = new GenericTextureFormat.Builder(); GetUnpalettedTools(version, clutFormat, depth, colorsCount, width, height, data, userdata, out imageCodec, out imgFilter); segment = builder.SetColorCodec(imageCodec) .SetMipmapsCount(mipmapsCount) .SetImageFilter(imgFilter) .Build(imgData, width, height); } segment.FormatSpecificData.Put <byte>(CLUTFORMAT_KEY, clutFormat) .Put <byte>(FORMAT_KEY, format) .Put <byte>(DEPTH_KEY, depth) .Put <byte[]>(DATA_KEY, data) .Put <byte[]>(USERDATA_KEY, userdata); return(segment); }
public override TextureFormat Open(System.IO.Stream formatData) { if (!IsValidFormat(formatData)) { throw new TextureFormatException("Not a valid TPL Texture!"); } BinaryReader reader = new BinaryReader(formatData); reader.BaseStream.Position += 4; ByteOrder order = ByteOrder.BigEndian; int texturesCount = (int)reader.ReadUInt32(order); uint imageTableOffset = reader.ReadUInt32(order); reader.BaseStream.Position = imageTableOffset; TPLTexture texture = new TPLTexture(); for (int i = 0; i < texturesCount; i++) { TextureFormat segment = null; //image table uint imageHeaderOffset = reader.ReadUInt32(order); uint offsetPaletteHeader = reader.ReadUInt32(order); long oldPos = reader.BaseStream.Position; reader.BaseStream.Position = imageHeaderOffset; int height = reader.ReadUInt16(order); int width = reader.ReadUInt16(order); uint format = reader.ReadUInt32(order); uint imgDataOffset = reader.ReadUInt32(order); ColorCodec colorCodec = null; IndexCodec idxCodec = null; ImageFilter imgFilter = null; ushort entryCount = 0; ushort unknown = 0;//this might be a set of flags denoting whether the palette is internal to the tpl image or external. uint paletteFormat = 0; uint palDataOffset = 0; bool isIndexed = false; int imgDataSize = 0; int palDataSize = 0; switch (format) { case 0: //I4 colorCodec = ColorCodec.CODEC_4BITBE_I4; imgFilter = new TileFilter(4, 8, 8, width, height); imgDataSize = colorCodec.GetBytesNeededForEncode(width, height, imgFilter); break; case 1: //I8 colorCodec = ColorCodec.CODEC_8BIT_I8; imgFilter = new TileFilter(8, 8, 4, width, height); imgDataSize = colorCodec.GetBytesNeededForEncode(width, height, imgFilter); break; case 2: //IA4 colorCodec = ColorCodec.CODEC_8BITBE_IA4; imgFilter = new TileFilter(8, 8, 4, width, height); imgDataSize = colorCodec.GetBytesNeededForEncode(width, height, imgFilter); break; case 3: //IA8 colorCodec = ColorCodec.CODEC_16BITBE_IA8; imgFilter = new TileFilter(16, 4, 4, width, height); imgDataSize = colorCodec.GetBytesNeededForEncode(width, height, imgFilter); break; case 4: //RGB565 colorCodec = ColorCodec.CODEC_16BITBE_RGB565; imgFilter = new TileFilter(16, 4, 4, width, height); imgDataSize = colorCodec.GetBytesNeededForEncode(width, height, imgFilter); break; case 5: //RGB5A3 colorCodec = ColorCodec.CODEC_16BITBE_RGB5A3; imgFilter = new TileFilter(16, 4, 4, width, height); imgDataSize = colorCodec.GetBytesNeededForEncode(width, height, imgFilter); break; case 6: //RGBA32 2 planes colorCodec = ColorCodec.CODEC_32BIT_ARGB; imgFilter = new ImageFilterComposer { new GamecubePlanarFilter(), new TileFilter(32, 4, 4, width, height) }; imgDataSize = colorCodec.GetBytesNeededForEncode(width, height, imgFilter); break; case 8: //C4 case 9: //C8 isIndexed = true; reader.BaseStream.Position = offsetPaletteHeader; entryCount = reader.ReadUInt16(order); unknown = reader.ReadUInt16(order); paletteFormat = reader.ReadUInt32(order); palDataOffset = reader.ReadUInt32(order); switch (paletteFormat) { case 0: colorCodec = ColorCodec.CODEC_16BITBE_IA8; break; case 1: colorCodec = ColorCodec.CODEC_16BITBE_RGB565; break; case 2: colorCodec = ColorCodec.CODEC_16BITBE_RGB5A3; break; default: throw new TextureFormatException("Unsupported palette format " + paletteFormat); } palDataSize = colorCodec.GetBytesNeededForEncode(entryCount, 1); if (format == 8) { idxCodec = IndexCodec.FromBitPerPixel(4, order); imgFilter = new TileFilter(4, 8, 8, width, height); } else { idxCodec = IndexCodec.FromBitPerPixel(8, order); imgFilter = new TileFilter(8, 8, 4, width, height); } imgDataSize = idxCodec.GetBytesNeededForEncode(width, height, imgFilter); break; case 0xA: //C14X2 throw new TextureFormatException("C14X2 not implemented yet!"); break; case 0xE: //DXT1 (aka CMPR) colorCodec = new ColorCodecDXT1Gamecube(width, height); imgDataSize = colorCodec.GetBytesNeededForEncode(width, height); break; default: throw new TextureFormatException("Unsupported TPL image format " + format); } reader.BaseStream.Position = imgDataOffset; byte[] imgData = reader.ReadBytes(imgDataSize); if (isIndexed) { reader.BaseStream.Position = palDataOffset; byte[] palData = reader.ReadBytes(palDataSize); PalettedTextureFormat.Builder builder = new PalettedTextureFormat.Builder(); segment = builder.SetIndexCodec(idxCodec) .SetPaletteCodec(colorCodec) .SetImageFilter(imgFilter) .Build(imgData, palData, width, height); } else { GenericTextureFormat.Builder builder = new GenericTextureFormat.Builder(); segment = builder.SetColorCodec(colorCodec) .SetImageFilter(imgFilter) .Build(imgData, width, height); } segment.FormatSpecificData.Put <uint>(FORMAT_KEY, format) .Put <uint>(UNKNOWN_KEY, unknown) .Put <uint>(PALETTEFORMAT_KEY, paletteFormat); texture.TextureFormats.Add(segment); reader.BaseStream.Position = oldPos; } return(texture); }
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); }