public void UpdateBitmapList(BitmapList BitmapList) { var Bitmaps = BitmapList.Bitmaps; if (BitmapList.Bitmaps.Length == 0) { throw(new Exception("Empty BitmapList")); } if (BitmapList.Bitmaps.Length != Depth) { throw (new Exception(String.Format("Invalid dimensions {0}x{1}x{2} != {2}x{3}x{4}", Bitmaps[0].Width, Bitmaps[0].Height, Bitmaps.Length, Width, Height, Depth))); } if (Bitmaps[0].Width != Width || Bitmaps[0].Height != Height) { throw (new Exception(String.Format("Invalid dimensions {0}x{1} != {2}x{3}", Bitmaps[0].Width, Bitmaps[0].Height, Width, Height))); } switch (ImageEntry.ImageFileFormat.TextureFormat) { case GPUTEXTUREFORMAT.GPUTEXTUREFORMAT_DXT4_5: (new DXT5()).SaveSwizzled3D(BitmapList, this.SliceStream.Slice(), CompressDXT.CompressionMode.Normal); break; case GPUTEXTUREFORMAT.GPUTEXTUREFORMAT_DXT1: (new DXT1()).SaveSwizzled3D(BitmapList, this.SliceStream.Slice(), CompressDXT.CompressionMode.Normal); break; default: throw (new NotImplementedException()); } }
/// <summary> /// /// </summary> /// <param name="Bitmap"></param> /// <param name="Stream"></param> /// <param name="mode"></param> public void SaveSwizzled3D(BitmapList BitmapList, Stream Stream, CompressDXT.CompressionMode mode = CompressDXT.CompressionMode.Normal, bool ShowWarnings = false) { int Width = BitmapList.Bitmaps[0].Width, Height = BitmapList.Bitmaps[0].Height, Depth = BitmapList.Bitmaps.Length; if ((Width % 4) != 0 || (Height % 4) != 0) { throw (new InvalidDataException()); } BitmapList.LockUnlockBits(PixelFormat.Format32bppArgb, (BitmapDatas) => { var Bases = new ARGB_Rev *[Depth]; for (int n = 0; n < Depth; n++) { Bases[n] = (ARGB_Rev *)BitmapDatas[n].Scan0.ToPointer(); } int BlockWidth = Width / 4; int BlockHeight = Height / 4; //var BlockCount = BlockWidth * BlockHeight; var ExpectedBlockCount = BlockWidth * BlockHeight * Depth; int RealUsedBlockCount; //RealUsedBlockCount = Swizzling.XGAddress2DTiledExtent(BlockWidth, BlockHeight, BlockSize); RealUsedBlockCount = Swizzling.XGAddress3DTiledExtent(BlockWidth, BlockHeight, Depth, BlockSize); //Console.WriteLine("{0} - {1}", ExpectedBlockCount, UsedBlockCount); var BlockCount = RealUsedBlockCount; var CurrentDecodedColors = new ARGB_Rev[4 * 4]; var Blocks = new TBlock[(uint)BlockCount]; for (int dxt5_n = 0; dxt5_n < BlockCount; dxt5_n++) { int TileX, TileY, TileZ; Swizzling.XGAddress3DTiledXYZ(dxt5_n, BlockWidth, BlockHeight, BlockSize, out TileX, out TileY, out TileZ); int PositionX = TileX * 4; int PositionY = TileY * 4; int PositionZ = TileZ; int n = 0; if ((PositionX + 3 >= Width) || (PositionY + 3 >= Height) || (PositionZ >= Depth)) { if (ShowWarnings) { Console.Error.WriteLine("(Warning! [Write] Position outside ({0}, {1}, {2}) - ({3}x{4}x{5}))", PositionX, PositionY, PositionZ, Width, Height, Depth); } continue; } for (int y = 0; y < 4; y++) { for (int x = 0; x < 4; x++) { CurrentDecodedColors[n] = Bases[TileZ][(PositionY + y) * Width + (PositionX + x)]; n++; } } //for (n = 0; n < 16; n++) CurrentDecodedColors[n] = new ARGB_Rev(0xFF, 0xFF, 0, (byte)(n * 16)); EncodeBlock(ref Blocks[dxt5_n], ref CurrentDecodedColors, mode); } //File.WriteAllBytes(@"C:\temp\font\test.txv", StructUtils.StructArrayToBytes(Blocks)); //Console.WriteLine(Blocks.Length * Marshal.SizeOf(typeof(TBlock))); Stream.WriteStructVector(Blocks); Stream.Flush(); }); }
/// <summary> /// /// </summary> /// <param name="File"></param> /// <param name="Width"></param> /// <param name="Height"></param> /// <param name="_Depth"></param> /// <param name="Swizzled"></param> /// <returns></returns> private BitmapList _LoadSwizzled(Stream File, int Width, int Height, int?_Depth, bool Swizzled = true) { if ((Width % 4) != 0 || (Height % 4) != 0) { throw (new InvalidDataException(String.Format("Invalid size {0}x{1} must be multiple of 4", Width, Height))); } int Depth = _Depth ?? 1; bool Is3D = _Depth.HasValue; var BitmapList = new BitmapList(Depth); var BitmapListData = new BitmapData[Depth]; var BitmapListPointers = new ARGB_Rev *[Depth]; for (int n = 0; n < Depth; n++) { BitmapList.Bitmaps[n] = new Bitmap(Width, Height); } for (int n = 0; n < Depth; n++) { var Bitmap = BitmapList.Bitmaps[n]; BitmapListData[n] = Bitmap.LockBits(Bitmap.GetFullRectangle(), ImageLockMode.WriteOnly, PixelFormat.Format32bppArgb); BitmapListPointers[n] = (ARGB_Rev *)BitmapListData[n].Scan0.ToPointer(); } int BlockWidth = Width / 4; int BlockHeight = Height / 4; var CurrentDecodedColors = new ARGB_Rev[4 * 4]; var ExpectedBlockCount = BlockWidth * BlockHeight * Depth; int RealUsedBlockCount; if (Is3D) { RealUsedBlockCount = Swizzling.XGAddress3DTiledExtent(Width / 4, Height / 4, Depth, BlockSize); } else { RealUsedBlockCount = Swizzling.XGAddress2DTiledExtent(Width / 4, Height / 4, BlockSize); } //Console.WriteLine("{0} - {1}", ExpectedBlockCount, UsedBlockCount); var BlockCount = RealUsedBlockCount; //var BlockCount = ExpectedBlockCount; if (BlockCount * Marshal.SizeOf(typeof(TBlock)) > File.Length) { Console.Error.WriteLine("File too small"); //throw(new Exception("File too small")); return(new BitmapList(0)); } var Blocks = File.ReadStructVector <TBlock>((uint)BlockCount, -1); //Console.WriteLine(Blocks.Length); for (int BlockN = 0; BlockN < BlockCount; BlockN++) { int TileX, TileY, TileZ; if (Swizzled) { if (Is3D) { Swizzling.XGAddress3DTiledXYZ(BlockN, BlockWidth, BlockHeight, BlockSize, out TileX, out TileY, out TileZ); } else { Swizzling.XGAddress2DTiledXY(BlockN, BlockWidth, BlockSize, out TileX, out TileY); TileZ = 0; } } else { TileX = BlockN % BlockWidth; TileY = BlockN / BlockWidth; TileZ = 0; Console.Error.Write("(Not implemented!)"); } // Skip blocks. if (TileX >= BlockWidth || TileY >= BlockHeight) { continue; } DecodeBlock(ref Blocks[BlockN], ref CurrentDecodedColors); //Console.WriteLine("{0}", CurrentDecodedColors[0]); int PositionX = TileX * 4; int PositionY = TileY * 4; var BlockBitmap = BitmapList.Bitmaps[TileZ]; if ((PositionX + 3 >= BlockBitmap.Width) || (PositionY + 3 >= BlockBitmap.Height)) { Console.Error.WriteLine( "(Warning! [Read] Position outside ({0}, {1}) - ({2}x{3}) ;; ({4}, {5})) - ({6}x{7}) ;; {8}", PositionX, PositionY, Width, Height, TileX, TileY, BlockWidth, BlockHeight, BlockN ); continue; } int n = 0; var BitmapPointer = BitmapListPointers[TileZ]; for (int y = 0; y < 4; y++) { int BaseOffset = (PositionY + y) * Width + (PositionX); for (int x = 0; x < 4; x++) { BitmapPointer[BaseOffset + x] = CurrentDecodedColors[n]; n++; } } } for (int n = 0; n < Depth; n++) { BitmapList.Bitmaps[n].UnlockBits(BitmapListData[n]); } return(BitmapList); }