public IMGC(Stream input) { using (var br = new BinaryReaderX(input, true)) { //Header header = br.ReadType <IMGCHeader>(); if (header.imageFormat == 28 && header.bitDepth == 8) { editMode = true; header.imageFormat = 29; } //get tile table br.BaseStream.Position = header.tableDataOffset; var tableC = br.ReadBytes(header.tableSize1); tableComp = (CompressionMethod)(tableC[0] & 0x7); byte[] table = Compressor.Decompress(new MemoryStream(tableC)); //get image data br.BaseStream.Position = header.tableDataOffset + header.tableSize2; var texC = br.ReadBytes(header.imgDataSize); picComp = (CompressionMethod)(texC[0] & 0x7); byte[] tex = Compressor.Decompress(new MemoryStream(texC)); //order pic blocks by table byte[] pic = Order(new MemoryStream(table), new MemoryStream(tex)); //return finished image settings = new ImageSettings(Support.Format[header.imageFormat], header.width, header.height) { Swizzle = new ImgcSwizzle(header.width, header.height) }; Image = Kolors.Load(pic, settings); } }
/// <summary> /// /// </summary> /// <param name="input"></param> public BTX(Stream input) { using (var br = new BinaryReaderX(input, true)) { // Header Header = br.ReadType <FileHeader>(); br.SeekAlignment(); FileName = br.ReadCStringASCII(); // Setup var dataLength = Header.Width * Header.Height; var paletteDataLength = Header.ColorCount * 4; // Image br.BaseStream.Position = Header.ImageOffset; var texture = br.ReadBytes(dataLength); // Palette if (Header.Format == ImageFormat.Palette_8) { br.BaseStream.Position = Header.PaletteOffset; var palette = br.ReadBytes(paletteDataLength); var settings = new IndexedImageSettings(IndexEncodings[(int)Header.Format], PaletteEncodings[(int)Header.Format], Header.Width, Header.Height); var data = Kolors.Load(texture, palette, settings); Texture = data.image; Palette = data.palette; FormatName = IndexEncodings[(int)Header.Format].FormatName; PaletteFormatName = PaletteEncodings[(int)Header.Format].FormatName; HasPalette = true; } else { var settings = new ImageSettings(Encodings[(int)Header.Format], Header.Width, Header.Height); Texture = Kolors.Load(texture, settings); FormatName = Encodings[(int)Header.Format].FormatName; } } }
public TEX(Stream input) { using (var br = new BinaryReaderX(input)) { // Set endianess if (br.PeekString() == "\0XET") { br.ByteOrder = ByteOrder = ByteOrder.BigEndian; } // Header Header = br.ReadType <FileHeader>(); HeaderInfo = new FileHeaderInfo { // Block 1 Version = (Version)(Header.Block1 & 0xFFF), Unknown1 = (int)((Header.Block1 >> 12) & 0xFFF), Unused1 = (int)((Header.Block1 >> 24) & 0xF), AlphaChannelFlags = (AlphaChannelFlags)((Header.Block1 >> 28) & 0xF), // Block 2 MipMapCount = (int)(Header.Block2 & 0x3F), Width = (int)((Header.Block2 >> 6) & 0x1FFF), Height = Math.Max((int)((Header.Block2 >> 19) & 0x1FFF), MinHeight), // Block 3 Unknown2 = (int)(Header.Block3 & 0xFF), Format = (byte)((Header.Block3 >> 8) & 0xFF), Unknown3 = (int)((Header.Block3 >> 16) & 0xFFFF) }; if (HeaderInfo.Version == Version._Switchv1 && !SwitchFormats.ContainsKey(HeaderInfo.Format)) { throw new InvalidOperationException($"Switch texture format 0x{HeaderInfo.Format.ToString("X2")} is not implemented."); } else if (!Formats.ContainsKey(HeaderInfo.Format)) { throw new InvalidOperationException($"Texture format 0x{HeaderInfo.Format.ToString("X2")} is not implemented."); } // TODO: Consider whether the following settings make more sense if conditioned by the ByteOrder (or Platform) //var format = HeaderInfo.Format.ToString().StartsWith("DXT1") ? Format.DXT1 : HeaderInfo.Format.ToString().StartsWith("DXT5") ? Format.DXT5 : HeaderInfo.Format; var encoding = (HeaderInfo.Version == Version._Switchv1) ? SwitchFormats[HeaderInfo.Format] : Formats[HeaderInfo.Format]; List <int> mipMaps = null; if (HeaderInfo.Version == Version._Switchv1) { var texOverallSize = br.ReadInt32(); if (texOverallSize > br.BaseStream.Length) { br.BaseStream.Position -= 4; SwitchUnknownData = br.ReadBytes(0x6C); texOverallSize = br.ReadInt32(); HeaderInfo.MipMapCount++; } mipMaps = br.ReadMultiple <int>(HeaderInfo.MipMapCount); } else if (HeaderInfo.Version != Version._3DSv1) { mipMaps = br.ReadMultiple <int>(HeaderInfo.MipMapCount); } for (var i = 0; i < mipMaps.Count; i++) { var texDataSize = 0; if (SwitchUnknownData != null) { if (i + 1 == HeaderInfo.MipMapCount) { continue; } texDataSize = mipMaps[i + 1] - mipMaps[i]; } else if (HeaderInfo.Version != Version._3DSv1) { texDataSize = (i + 1 < HeaderInfo.MipMapCount ? mipMaps[i + 1] : (int)br.BaseStream.Length) - mipMaps[i]; } else { texDataSize = Formats[HeaderInfo.Format].BitDepth * (HeaderInfo.Width >> i) * (HeaderInfo.Height >> i) / 8; } Settings = new ImageSettings(encoding, Math.Max(HeaderInfo.Width >> i, 2), Math.Max(HeaderInfo.Height >> i, 2)); //Set possible Swizzles if (HeaderInfo.Version == Version._3DSv1 || HeaderInfo.Version == Version._3DSv2 || HeaderInfo.Version == Version._3DSv3) { Settings.Swizzle = new CTRSwizzle(Settings.Width, Settings.Height, CtrTransformation.None, true); } else if (HeaderInfo.Version == Version._Switchv1) { Settings.Swizzle = new SwitchSwizzle(Settings.Width, Settings.Height, Settings.Encoding.BitDepth, GetSwitchSwizzleFormat(Settings.Encoding.FormatName), true); } else if (Settings.Encoding.FormatName.Contains("DXT")) { Settings.Swizzle = new BCSwizzle(Settings.Width, Settings.Height); } //Set possible pixel shaders if ((Format)HeaderInfo.Format == Format.DXT5_B) { Settings.PixelShader = ToNoAlpha; } else if ((Format)HeaderInfo.Format == Format.DXT5_YCbCr) { Settings.PixelShader = ToProperColors; } EncodingInfo info = null; if (HeaderInfo.Version == Version._3DSv1 || HeaderInfo.Version == Version._3DSv2 || HeaderInfo.Version == Version._3DSv3) { info = EncodingInfos.First(x => x.EncodingIndex == HeaderInfo.Format); } else if (HeaderInfo.Version == Version._Switchv1) { info = SwitchEncodingInfos.First(x => x.EncodingIndex == HeaderInfo.Format); } if (i == 0) { Bitmaps.Add(new BitmapInfo(Kolors.Load(br.ReadBytes(texDataSize), Settings), info)); } else { Bitmaps[0].MipMaps.Add(Kolors.Load(br.ReadBytes(texDataSize), Settings)); } } if (SwitchUnknownData != null) { SwitchOverflowingData = br.ReadBytes((int)(br.BaseStream.Length - br.BaseStream.Position)); } } }