public Bitmap CompressColors(Bitmap Bitmap, CompressDXT.CompressionMode mode = CompressDXT.CompressionMode.Normal, int ReduceColors = 4) { var TempStream = new MemoryStream(); SaveSwizzled2D(Bitmap, TempStream, mode, ReduceColors); return(LoadSwizzled2D(TempStream.Slice(), Bitmap.Width, Bitmap.Height)); }
protected override void EncodeBlock(ref DXT5.AlphaColorBlock Block, ref ARGB_Rev[] Colors, CompressDXT.CompressionMode CompressionMode) { CompressDXT.CompressBlockDXT5(Colors, out Block, CompressionMode); }
/// <summary> /// /// </summary> /// <param name="Block"></param> /// <param name="Colors"></param> /// <param name="CompressionMode"></param> abstract protected void EncodeBlock(ref TBlock Block, ref ARGB_Rev[] Colors, CompressDXT.CompressionMode CompressionMode);
/// <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(); }); }
//static private ARGB_Rev FindNearColorInPalette(IEnumerable<ARGB_Rev> Palette, ARGB_Rev Color) //{ // return Palette.OrderBy(PaletteColor => ARGB_Rev.DistanceRGB(PaletteColor, Color)).First(); //} // //static private ARGB_Rev FindFarColorInPalette(IEnumerable<ARGB_Rev> Palette, ARGB_Rev Color) //{ // return Palette.OrderBy(PaletteColor => ARGB_Rev.DistanceRGB(PaletteColor, Color)).Last(); //} // //static private ARGB_Rev AverageColors(IEnumerable<ARGB_Rev> Palette) //{ // return new ARGB_Rev( // (byte)Palette.Average(Item => Item.A), // (byte)Palette.Average(Item => Item.R), // (byte)Palette.Average(Item => Item.G), // (byte)Palette.Average(Item => Item.B) // ); //} // //private void ReduceColors(List<ARGB_Rev> Palette, int ColorCount) //{ // while (Palette.Count > ColorCount) // { // Palette.Remove(FindNearColorInPalette(Palette, AverageColors(Palette))); // } //} // //private void DoReduceColors(ref ARGB_Rev[] Colors, int ColorCount) //{ // var ReducedColorsList = Colors.ToList(); // ReduceColors(ReducedColorsList, ColorCount); // //Console.WriteLine(String.Join(",", Colors.ToArray())); // //Console.WriteLine(String.Join(",", ReducedColorsList.ToArray())); // for (int n = 0; n < Colors.Length; n++) // { // Colors[n] = FindNearColorInPalette(ReducedColorsList, Colors[n]); // } //} /// <summary> /// /// </summary> /// <param name="Bitmap"></param> /// <param name="File"></param> /// <param name="mode"></param> public void SaveSwizzled2D(Bitmap Bitmap, Stream File, CompressDXT.CompressionMode mode = CompressDXT.CompressionMode.Normal, int ReduceColors = 16, bool ShowWarnings = false) { int Width = Bitmap.Width, Height = Bitmap.Height; if ((Width % 4) != 0 || (Height % 4) != 0) { throw (new InvalidDataException()); } Bitmap.LockBitsUnlock(PixelFormat.Format32bppArgb, (BitmapData) => { var Base = (ARGB_Rev *)BitmapData.Scan0.ToPointer(); int BlockWidth = Width / 4; int BlockHeight = Height / 4; //var BlockCount = BlockWidth * BlockHeight; var ExpectedBlockCount = BlockWidth * BlockHeight; int RealUsedBlockCount; RealUsedBlockCount = Swizzling.XGAddress2DTiledExtent(Width / 4, Height / 4, 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; Swizzling.XGAddress2DTiledXY(dxt5_n, BlockWidth, BlockSize, out TileX, out TileY); int PositionX = TileX * 4; int PositionY = TileY * 4; int n = 0; if ((PositionX + 3 >= Width) || (PositionY + 3 >= Height)) { if (ShowWarnings) { Console.Error.WriteLine("(Warning! [Write] Position outside ({0}, {1}) - ({2}x{3}))", PositionX, PositionY, Width, Height); } continue; } for (int y = 0; y < 4; y++) { for (int x = 0; x < 4; x++) { CurrentDecodedColors[n] = Base[(PositionY + y) * Width + (PositionX + x)]; n++; } } //if (ReduceColors != 16) DoReduceColors(ref CurrentDecodedColors, ReduceColors); EncodeBlock(ref Blocks[dxt5_n], ref CurrentDecodedColors, mode); } File.WriteStructVector(Blocks); File.Flush(); }); }