示例#1
0
        static private void RefineMinMax(ARGB_Rev[] Colors, ref ARGB_Rev Min, ref ARGB_Rev Max)
        {
            int MinListCount = 0;
            int MaxListCount = 0;
            var MinAccum     = default(RGBA32);
            var MaxAccum     = default(RGBA32);

            foreach (var color in Colors)
            {
                int DistanceMin = ARGB_Rev.DistanceRGB(color, Min);
                int DistanceMax = ARGB_Rev.DistanceRGB(color, Max);

                if (DistanceMin <= DistanceMax)
                {
                    MinAccum += color;
                    MinListCount++;
                }

                if (DistanceMax <= DistanceMin)
                {
                    MaxAccum += color;
                    MaxListCount++;
                }
            }

            Min   = MinAccum / MinListCount;
            Max   = MaxAccum / MaxListCount;
            Min.A = 0xFF;
            Max.A = 0xFF;
        }
示例#2
0
文件: DXT1.cs 项目: talestra/tov
            internal void Decode(ref ARGB_Rev[] output)
            {
                var color_table = new ARGB_Rev[4];

                color_table[0] = ColorUtils.Encode(ColorFormats.RGBA_5650, colors0);
                color_table[1] = ColorUtils.Encode(ColorFormats.RGBA_5650, colors1);
                MathUtils.Swap(ref color_table[0].R, ref color_table[0].B);
                MathUtils.Swap(ref color_table[1].R, ref color_table[1].B);

                // Color table.
                if (colors0 > colors1)
                {
                    color_table[2] = ColorUtils.Mix(color_table[0], color_table[1], 3, 2, 1);
                    color_table[3] = ColorUtils.Mix(color_table[0], color_table[1], 3, 1, 2);
                }
                else
                {
                    color_table[2] = ColorUtils.Mix(color_table[0], color_table[1], 2, 1, 1);
                    color_table[3] = Color.FromArgb(0, 0, 0, 0);
                }

                var color_data_transfer = new byte[16];

                transferColorData(ref color_data_transfer, extract: true);
                for (int n = 0; n < 16; n++)
                {
                    output[n] = color_table[color_data_transfer[n]];
                }
            }
示例#3
0
文件: Y_CO_CG_A.cs 项目: talestra/tov
 static public Y_CO_CG_A ConvertRGBToCoCg_Y(ARGB_Rev Input)
 {
     return(new Y_CO_CG_A()
     {
         CO = CLAMP_BYTE(RGB_TO_YCOCG_CO(Input) + 128),
         CG = CLAMP_BYTE(RGB_TO_YCOCG_CG(Input) + 128),
         A = Input.A,
         Y = CLAMP_BYTE(RGB_TO_YCOCG_Y(Input)),
     });
 }
示例#4
0
 static public ARGB_Rev[] GeneratePallete2(ARGB_Rev C0, ARGB_Rev C1)
 {
     return(new ARGB_Rev[]
     {
         C0,
         C1,
         new ARGB_Rev(0, 0, 0, 0),
         ColorUtils.Mix(C0, C1, 2, 1, 1),
     });
 }
示例#5
0
 static public ARGB_Rev[] GeneratePallete1(ARGB_Rev C0, ARGB_Rev C1)
 {
     return(new ARGB_Rev[]
     {
         C0,
         C1,
         ColorUtils.Mix(C0, C1, 3, 2, 1),
         ColorUtils.Mix(C0, C1, 3, 1, 2),
     });
 }
示例#6
0
        /// <summary>
        ///
        /// </summary>
        /// <param name="_out"></param>
        /// <param name="v"></param>
        static void stb__From16Bit(out ARGB_Rev _out, ushort v)
        {
            int rv = (v & 0xf800) >> 11;
            int gv = (v & 0x07e0) >> 5;
            int bv = (v & 0x001f) >> 0;

            _out.R = stb__Expand5[rv];
            _out.G = stb__Expand6[gv];
            _out.B = stb__Expand5[bv];
            _out.A = 0;
        }
示例#7
0
文件: DXT5Test.cs 项目: talestra/tov
        public void TestDecodeBlock()
        {
            var Block1Data = new byte[] { 0xD5, 0x5B, 0x5D, 0xB2, 0x49, 0x00, 0xFF, 0xB2, 0xE6, 0xF6, 0xDE, 0x94, 0xFF, 0xFF, 0x02, 0xFE };

            var Block  = new MemoryStream(Block1Data).ReadStruct <DXT5.AlphaColorBlock>();
            var Colors = new ARGB_Rev[16];

            Block.Decode(ref Colors);

            Assert.AreEqual(
                "#E0D6A973,#E0D6A900,#E0D6A900,#E0D6A900,#E0D6A9BC,#E0D6A95B,#E0D6A95B,#E0D6A95B," +
                "#E3DAAED5,#E0D6A9D5,#E0D6A9D5,#E0D6A9D5,#E3DAAE8B,#E6DEB4FF,#E6DEB4FF,#E6DEB4FF"
                ,
                Colors.ToStringArray(",")
                );
        }
示例#8
0
文件: DXT5Test.cs 项目: talestra/tov
        public void TestCompressDXT5()
        {
            var Colors1 = new ARGB_Rev[16]
            {
                "#E0D6A973",
                "#E0D6A900",
                "#E0D6A900",
                "#E0D6A900",
                "#E0D6A9BC",
                "#E0D6A95B",
                "#E0D6A95B",
                "#E0D6A95B",
                "#E3DAAED5",
                "#E0D6A9D5",
                "#E0D6A9D5",
                "#E0D6A9D5",
                "#E3DAAE8B",
                "#E6DEB4FF",
                "#E6DEB4FF",
                "#E6DEB4FF",
            };

            var Colors2 = new ARGB_Rev[16];
            var Block   = default(DXT5.AlphaColorBlock);

            //var Color1 = default(ARGB_Rev);
            //var Color2 = default(ARGB_Rev);

            CompressDXT.CompressBlockDXT5(Colors1, out Block, CompressDXT.CompressionMode.Normal);

            Console.WriteLine(StructUtils.StructToBytes(Block).ToHexString().ToUpper());

            Block.Decode(ref Colors2);

            Assert.AreEqual(
                "#E0D6A973,#E0D6A900,#E0D6A900,#E0D6A900,#E0D6A9BC,#E0D6A95B,#E0D6A95B,#E0D6A95B,#E3DAAED5,#E0D6A9D5,#E0D6A9D5,#E0D6A9D5,#E3DAAE8B,#E6DEB4FF,#E6DEB4FF,#E6DEB4FF",
                Colors1.ToStringArray(",")
                );
            Assert.AreEqual(
                "#DED6AC6D,#DED6AC00,#DED6AC00,#DED6AC00,#DED6ACB6,#DED6AC6D,#DED6AC6D,#DED6AC6D,#E0D8AEDA,#DED6ACDA,#DED6ACDA,#DED6ACDA,#E0D8AE91,#E6DEB4FF,#E6DEB4FF,#E6DEB4FF",
                Colors2.ToStringArray(",")
                );

            //CompressionSimpleDXT5.FindColorPair(Colors1, out Color1, out Color2);

            //CompressYCoCgDXT5.CompressBlock(Colors1, ref Block);
        }
示例#9
0
        static public void FindColorPair(ARGB_Rev[] Colors, out ARGB_Rev Min, out ARGB_Rev Max)
        {
            FindBoundingBox(Colors, out Min, out Max);
            RefineMinMax(Colors, ref Min, ref Max);

            var Palette1 = GeneratePallete1(Min, Max);
            var Palette2 = GeneratePallete2(Min, Max);

            byte[] Indices1  = new byte[16];
            byte[] Indices2  = new byte[16];
            int    Distance1 = ColorToIndexed(Colors, Palette1, Indices1);
            int    Distance2 = ColorToIndexed(Colors, Palette2, Indices2);

            Console.WriteLine(Min);
            Console.WriteLine(Max);

            Console.WriteLine(Distance1);
            Console.WriteLine(Distance2);
        }
示例#10
0
        static public int ColorToIndexed(ARGB_Rev[] Colors, ARGB_Rev[] Palette, byte[] Indices)
        {
            int TotalDistance = 0;

            for (int n = 0; n < 16; n++)
            {
                var Color       = Colors[n];
                int MinDistance = int.MaxValue;
                int BestIndex   = 0;
                for (int m = 0; m < 4; m++)
                {
                    var Distance = ARGB_Rev.DistanceRGB(Color, Palette[m]);
                    if (Distance < MinDistance)
                    {
                        BestIndex   = m;
                        MinDistance = Distance;
                    }
                }
                TotalDistance += MinDistance;
                Indices[n]     = (byte)BestIndex;
            }
            return(TotalDistance);
        }
示例#11
0
        static public void DrawGlow(Bitmap Bitmap, DistanceEntry[,] _DistanceMap, float GlowDistance, ARGB_Rev GlowColor, Func <float, float> Function = null)
        {
            var TransparentColor = (ARGB_Rev)"#00000000";

            if (Function == null)
            {
                Function = (v) => v;
            }

            Bitmap.Shader((color, x, y) =>
            {
                var Dist = (float)_DistanceMap[x, y].Distance;
                if (Dist == 0 && color.A == 0xFF)
                {
                    return(color);
                }
                if (Dist > GlowDistance)
                {
                    return(new ARGB_Rev(0, 0, 0, 0));
                }
                var GenColor = ARGB_Rev.Interpolate(GlowColor, TransparentColor, 1 - Function(Dist / GlowDistance));
                return((Dist == 0) ? ARGB_Rev.Mix(color, GenColor) : GenColor);
            });
        }
示例#12
0
        static private void FindBoundingBox(ARGB_Rev[] Colors, out ARGB_Rev Min, out ARGB_Rev Max)
        {
            Min = Color.FromArgb(0xFF, 0xFF, 0xFF, 0x00);
            Max = Color.FromArgb(0x00, 0x00, 0x00, 0x00);

            foreach (var color in Colors)
            {
                Min.R = Math.Min(color.R, Min.R);
                Min.G = Math.Min(color.G, Min.G);
                Min.B = Math.Min(color.B, Min.B);
                //Min.A = Math.Min(color.A, Min.A);

                Max.R = Math.Max(color.R, Max.R);
                Max.G = Math.Max(color.G, Max.G);
                Max.B = Math.Max(color.B, Max.B);
                //Max.A = Math.Max(color.A, Max.A);
            }

            Min.A = 0xFF;
            Max.A = 0xFF;

            Console.WriteLine(Min);
            Console.WriteLine(Max);
        }
示例#13
0
		static public void DrawGlow(Bitmap Bitmap, DistanceEntry[,] _DistanceMap, float GlowDistance, ARGB_Rev GlowColor, float Min, float Max = 1.0f)
		{
			DistanceMap.DrawGlow(Bitmap, _DistanceMap, GlowDistance, GlowColor, (f) =>
			{
				return MathUtils.SmoothStep(Min, Max, f);
			});
		}
示例#14
0
文件: DXT.cs 项目: talestra/tov
        /// <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();
            });
        }
示例#15
0
文件: Y_CO_CG_A.cs 项目: talestra/tov
 static private int RGB_TO_YCOCG_CO(ARGB_Rev Color)
 {
     return((((Color.R << 1) - (Color.B << 1)) + 2) >> 2);
 }
示例#16
0
文件: Y_CO_CG_A.cs 项目: talestra/tov
 static private int RGB_TO_YCOCG_CG(ARGB_Rev Color)
 {
     return(((-Color.R + (Color.G << 1) - Color.B) + 2) >> 2);
 }
示例#17
0
 /// <summary>
 /// lerp RGB color
 /// </summary>
 /// <param name="_out"></param>
 /// <param name="p1"></param>
 /// <param name="p2"></param>
 static void stb__Lerp13RGB(ref ARGB_Rev _out, ARGB_Rev p1, ARGB_Rev p2)
 {
     _out.R = (byte)stb__Lerp13(p1.R, p2.R);
     _out.G = (byte)stb__Lerp13(p1.G, p2.G);
     _out.B = (byte)stb__Lerp13(p1.B, p2.B);
 }
示例#18
0
 static public void DrawGlow(Bitmap Bitmap, DistanceEntry[,] _DistanceMap, float GlowDistance, ARGB_Rev GlowColor, float Min, float Max = 1.0f)
 {
     DistanceMap.DrawGlow(Bitmap, _DistanceMap, GlowDistance, GlowColor, (f) =>
     {
         return(MathUtils.SmoothStep(Min, Max, f));
     });
 }
示例#19
0
文件: DXT.cs 项目: talestra/tov
        /// <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);
        }
示例#20
0
		static public void DrawGlow(Bitmap Bitmap, DistanceEntry[,] _DistanceMap, float GlowDistance, ARGB_Rev GlowColor, Func<float, float> Function = null)
		{
			var TransparentColor = (ARGB_Rev)"#00000000";

			if (Function == null) Function = (v) => v;

			Bitmap.Shader((color, x, y) =>
			{
				var Dist = (float)_DistanceMap[x, y].Distance;
				if (Dist == 0 && color.A == 0xFF) return color;
				if (Dist > GlowDistance) return new ARGB_Rev(0, 0, 0, 0);
				var GenColor = ARGB_Rev.Interpolate(GlowColor, TransparentColor, 1 - Function(Dist / GlowDistance));
				return (Dist == 0) ? ARGB_Rev.Mix(color, GenColor) : GenColor;
			});
		}
示例#21
0
文件: DXT.cs 项目: talestra/tov
        //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();
            });
        }