diff --git a/GUI/logic.py b/GUI/logic.py index 53ae2c4..d90c424 100644 --- a/GUI/logic.py +++ b/GUI/logic.py @@ -13,7 +13,6 @@ path_exporting = "" - def get_base_dir(): """Визначає реальну папку, навіть якщо це скомпільований .exe""" if getattr(sys, 'frozen', False): @@ -127,48 +126,17 @@ def run_subprocess(): "creationflags": subprocess.CREATE_NO_WINDOW} if sys.platform == "win32" else {} try: - # 1. Читаємо оригінальний великий CSV файл - with open(path_csv, 'r', encoding='utf-8') as f: - reader = csv.reader(f) - header = next(reader) - rows = list(reader) - - total_rows = len(rows) - # Кількість фото за один запуск (безпечно для 16GB RAM) - chunk_size = 500 - total_chunks = math.ceil(total_rows / chunk_size) - - # 2. Перебираємо і запускаємо пакети по черзі - for i in range(total_chunks): - chunk_rows = rows[i * chunk_size: (i + 1) * chunk_size] - - # Створюємо шлях до тимчасового файлу в тій самій папці - temp_csv = os.path.join(base_dir, f"temp_chunk_{i}.csv") - - with open(temp_csv, 'w', encoding='utf-8', newline='') as f: - writer = csv.writer(f) - writer.writerow(header) - writer.writerows(chunk_rows) - - # 3. Викликаємо C# ядро, передаючи йому ТИМЧАСОВИЙ файл замість основного! - result = subprocess.run( - [exe_path, temp_csv, path_config, path_template, path_exporting], - capture_output=True, text=True, **kwargs - ) - - # Одразу видаляємо шматок CSV, він нам більше не потрібен - if os.path.exists(temp_csv): - os.remove(temp_csv) - - # Якщо C# крашнувся на якомусь із пакетів - зупиняємо все і показуємо помилку - if result.returncode != 0: - messagebox.showerror(f"Error in batch file { - i+1}/{total_chunks}", result.stdout or result.stderr) - return - + result = subprocess.run( + [exe_path, path_csv, path_config, path_template, path_exporting], + capture_output=True, text=True, **kwargs + ) # 4. Якщо весь цикл пройшов без помилок - messagebox.showinfo("Success!", f"All { - total_rows} baners successfuly generated with batch files \n") + if result.returncode != 0: + messagebox.showerror( + "Error", f"Generator failed:\n{result.stderr}") + else: + messagebox.showinfo( + "Success!", "All baners successfuly generated with batch files \n") except Exception as e: messagebox.showerror("Critical Error", str(e)) diff --git a/Program.cs b/Program.cs index 734f691..f51ab0d 100644 --- a/Program.cs +++ b/Program.cs @@ -45,15 +45,9 @@ static void Main(string[] args) Console.WriteLine($"CSV: {csvPath} (Існує: {File.Exists(csvPath)})"); Console.WriteLine($"Config: {configPath} (Існує: {File.Exists(configPath)})"); Console.WriteLine($"Template: {templatePath} (Існує: {File.Exists(templatePath)})"); - Console.ReadLine(); return; } - Console.WriteLine("❌ Помилка: Не знайдено основні файли (config.json, data.csv або шаблон)!"); - Console.WriteLine($"CSV: {csvPath} (Існує: {File.Exists(csvPath)})"); - Console.WriteLine($"Config: {configPath} (Існує: {File.Exists(configPath)})"); - Console.WriteLine($"Template: {templatePath} (Існує: {File.Exists(templatePath)})"); - Directory.CreateDirectory(outputDir); // 1. Читання конфігу та CSV @@ -76,8 +70,6 @@ static void Main(string[] args) // 4. Формування звіту (Делегуємо сервісу) ReportService.GenerateReport(logs, reportPath); - Console.WriteLine("\nНатисніть Enter для виходу..."); - Console.ReadLine(); } } } diff --git a/Services/ImageBuilder.cs b/Services/ImageBuilder.cs index 7afcc3d..279a909 100644 --- a/Services/ImageBuilder.cs +++ b/Services/ImageBuilder.cs @@ -23,15 +23,10 @@ public static ConcurrentBag GenerateAll( var logs = new ConcurrentBag(); int processed = 0; - int imageWidth; - using (var tempImage = new MagickImage(templateBytes)) - { - imageWidth = (int)tempImage.Width; - } Func threadsProcent = (x) => Math.Max(1, (int)(Environment.ProcessorCount * x )); - int safeThreads = threadsProcent(0.5); + int safeThreads = threadsProcent(0.75); if(config.TryGetValue("GLOBAL_SETTINGS", out var max_threads) && max_threads.MaxThreads.HasValue) { @@ -51,13 +46,17 @@ public static ConcurrentBag GenerateAll( string outputPath = Path.Combine(outputDir, $"{filename}.avif"); + if(File.Exists(outputPath)) + { + logs.Add(new LogEntry(true, filename)); + return; + } + try { // 1. Відкриваємо колекцію шарів - using (var collection = new MagickImageCollection(templateBytes)) - { // 2. Сплющуємо шари в одне фонове зображення - using (var image = new MagickImage(collection[0])) + using (var image = new MagickImage(templateBytes)) { // image.Density = new Density(72, 72); int imageWidth = (int)image.Width; // Беремо ширину для вирівнювання по центру @@ -117,11 +116,11 @@ public static ConcurrentBag GenerateAll( // Малюємо і зберігаємо ТУТ, поки image ще існує image.Format = MagickFormat.Avif; - image.Quality = 90; + image.Quality = 80; + image.Settings.SetDefine("avif:speed", "6"); image.Write(outputPath); } // Тут image знищується і звільняє пам'ять - } // Тут collection знищується // Логування успішного збереження int currentCount = System.Threading.Interlocked.Increment(ref processed); diff --git a/Services/TemplateAnalyzer.cs b/Services/TemplateAnalyzer.cs index 80cdf1e..07804d8 100644 --- a/Services/TemplateAnalyzer.cs +++ b/Services/TemplateAnalyzer.cs @@ -11,40 +11,11 @@ public static class TemplateAnalyzer public static (byte[] TemplateBytes, Dictionary Coords) Analyze(string templatePath, Dictionary config) { - byte[] templateBytes; - var dynamicCoords = new Dictionary(); + var dynamicCoords = new Dictionary(); - using (var collection = new MagickImageCollection(templatePath)) - { - if (collection.Count > 1) - { - for (int i = collection.Count - 1; i >= 1; i--) - { - var layer = collection[i]; - string layerName = layer.GetAttribute("label") ?? layer.Label; + byte[] templateBytes = File.ReadAllBytes(templatePath); - if (!string.IsNullOrEmpty(layerName)) - { - var match = config.FirstOrDefault(c => - layerName.Equals(c.Value.PsdLayer ?? c.Key, StringComparison.OrdinalIgnoreCase)); - if(match.Key != null) - { - dynamicCoords[match.Key] = (layer.Page.X, layer.Page.Y); - Console.WriteLine($" 📍 Координати для '{match.Key}': X={layer.Page.X}, Y={layer.Page.Y}"); - collection.RemoveAt(i); - } - } - } - collection.RemoveAt(0); - using var cleanBackground = collection.Flatten(); - templateBytes = cleanBackground.ToByteArray(); - } - else - { - templateBytes = collection[0].ToByteArray(); - } - } - return (templateBytes, dynamicCoords); + return (templateBytes, dynamicCoords); } } }