using System; using System.IO; using System.Drawing; using System.Drawing.Imaging; using System.Collections.Generic; public class ImageProcessor { public static void MakeCleanTransparent(string inputPath, string outputPath) { using var original = (Bitmap)Image.FromFile(inputPath); int w = original.Width; int h = original.Height; using var bmp = new Bitmap(w, h, PixelFormat.Format32bppArgb); using (var g = Graphics.FromImage(bmp)) { g.DrawImage(original, 0, 0, w, h); } var rect = new Rectangle(0, 0, w, h); var data = bmp.LockBits(rect, ImageLockMode.ReadWrite, PixelFormat.Format32bppArgb); int bytesPerPixel = 4; int byteCount = data.Stride * h; byte[] pixels = new byte[byteCount]; System.Runtime.InteropServices.Marshal.Copy(data.Scan0, pixels, 0, byteCount); bool[,] isBg = new bool[w, h]; var queue = new Queue(); bool CheckWhite(int x, int y) { int idx = y * data.Stride + x * bytesPerPixel; byte b = pixels[idx]; byte g = pixels[idx + 1]; byte r = pixels[idx + 2]; // Pure/near white or light background return r > 215 && g > 215 && b > 215 && Math.Abs(r - g) < 25 && Math.Abs(g - b) < 25; } // Seed borders for (int x = 0; x < w; x++) { if (CheckWhite(x, 0)) { isBg[x, 0] = true; queue.Enqueue(new Point(x, 0)); } if (CheckWhite(x, h - 1)) { isBg[x, h - 1] = true; queue.Enqueue(new Point(x, h - 1)); } } for (int y = 0; y < h; y++) { if (CheckWhite(0, y)) { isBg[0, y] = true; queue.Enqueue(new Point(0, y)); } if (CheckWhite(w - 1, y)) { isBg[w - 1, y] = true; queue.Enqueue(new Point(w - 1, y)); } } int[] dx = { 0, 0, 1, -1 }; int[] dy = { 1, -1, 0, 0 }; while (queue.Count > 0) { var p = queue.Dequeue(); for (int i = 0; i < 4; i++) { int nx = p.X + dx[i]; int ny = p.Y + dy[i]; if (nx >= 0 && nx < w && ny >= 0 && ny < h && !isBg[nx, ny]) { if (CheckWhite(nx, ny)) { isBg[nx, ny] = true; queue.Enqueue(new Point(nx, ny)); } } } } // Apply transparency for (int y = 0; y < h; y++) { for (int x = 0; x < w; x++) { int idx = y * data.Stride + x * bytesPerPixel; if (isBg[x, y]) { pixels[idx + 3] = 0; // Alpha = 0 } else { // Check if adjacent to background for soft anti-aliased edge bool nearBg = false; for (int i = 0; i < 4; i++) { int nx = x + dx[i]; int ny = y + dy[i]; if (nx >= 0 && nx < w && ny >= 0 && ny < h && isBg[nx, ny]) { nearBg = true; break; } } byte b = pixels[idx]; byte g = pixels[idx + 1]; byte r = pixels[idx + 2]; if (nearBg && r > 210 && g > 210 && b > 210) { double avg = (r + g + b) / 3.0; int alpha = (int)(255.0 * (1.0 - (avg - 210.0) / 45.0)); pixels[idx + 3] = (byte)Math.Clamp(alpha, 0, 255); } } } } System.Runtime.InteropServices.Marshal.Copy(pixels, 0, data.Scan0, byteCount); bmp.UnlockBits(data); // Ensure output dir var dir = Path.GetDirectoryName(outputPath); if (!string.IsNullOrEmpty(dir)) Directory.CreateDirectory(dir); bmp.Save(outputPath, ImageFormat.Png); Console.WriteLine($"Exported: {outputPath}"); } public static void Main(string[] args) { string brain = @"C:\Users\mvrba\.gemini\antigravity\brain\f097144f-e914-4120-8461-4bdfe0d3cdef"; string root = @"src\CiselnaVyprava\wwwroot\assets\images"; // 1. Knight (Exact same boy character) string knightIdleSrc = Path.Combine(brain, "disney_hero_knight_1789996129818.jpg"); string knightAtkSrc = Path.Combine(brain, "knight_action_strike_1789998031553.jpg"); string knightDefSrc = Path.Combine(brain, "knight_action_shield_1789998042563.jpg"); string knightDizzySrc = Path.Combine(brain, "hero_knight_dizzy_1789997064946.jpg"); // 2. Goblin string goblinIdleSrc = Path.Combine(brain, "disney_monster_goblin_1789996145106.jpg"); string goblinAtkSrc = Path.Combine(brain, "goblin_monster_attack_1789997081347.jpg"); string goblinHurtSrc = Path.Combine(brain, "goblin_monster_hurt_1789997090819.jpg"); // 3. Golem Boss string golemSrc = Path.Combine(brain, "stone_golem_boss_1789997102336.jpg"); // Process Knight for (int p = 1; p <= 4; p++) { string idleSrc = (p <= 2) ? knightIdleSrc : knightDizzySrc; MakeCleanTransparent(idleSrc, Path.Combine(root, $"heroes/knight_idle_p{p}.png")); MakeCleanTransparent(knightAtkSrc, Path.Combine(root, $"heroes/knight_attack_p{p}.png")); MakeCleanTransparent(knightDefSrc, Path.Combine(root, $"heroes/knight_defend_p{p}.png")); MakeCleanTransparent(knightDizzySrc, Path.Combine(root, $"heroes/knight_hurt_p{p}.png")); } // Process Goblin & Slime for (int p = 1; p <= 4; p++) { MakeCleanTransparent(goblinIdleSrc, Path.Combine(root, $"enemies/goblin_idle_p{p}.png")); MakeCleanTransparent(goblinAtkSrc, Path.Combine(root, $"enemies/goblin_attack_p{p}.png")); MakeCleanTransparent(goblinHurtSrc, Path.Combine(root, $"enemies/goblin_hurt_p{p}.png")); MakeCleanTransparent(goblinIdleSrc, Path.Combine(root, $"enemies/slime_idle_p{p}.png")); MakeCleanTransparent(goblinAtkSrc, Path.Combine(root, $"enemies/slime_attack_p{p}.png")); MakeCleanTransparent(goblinHurtSrc, Path.Combine(root, $"enemies/slime_hurt_p{p}.png")); } // Process Golem for (int p = 1; p <= 4; p++) { MakeCleanTransparent(golemSrc, Path.Combine(root, $"enemies/golem_idle_p{p}.png")); MakeCleanTransparent(golemSrc, Path.Combine(root, $"enemies/golem_attack_p{p}.png")); MakeCleanTransparent(golemSrc, Path.Combine(root, $"enemies/golem_hurt_p{p}.png")); } Console.WriteLine("All assets converted to clean 32-bit transparent PNGs!"); } }