From 5d70b4c54b8b3377ff91f4d87f13986ed3a356be Mon Sep 17 00:00:00 2001 From: Colin McMillen Date: Wed, 30 Aug 2023 17:57:01 -0400 Subject: [PATCH] ExportPhotos(): add progress on statusbar, skip if already exporting --- Program.cs | 50 ++++++++++++++++++++++++++++++++++++++------------ 1 file changed, 38 insertions(+), 12 deletions(-) diff --git a/Program.cs b/Program.cs index 32d0c28..cc4c50e 100644 --- a/Program.cs +++ b/Program.cs @@ -386,8 +386,8 @@ public class Game : GameWindow { geometry = new UiGeometry(nwSettings.Size, STAR_FILLED.Size.X); } - // private static string outputRoot = @"c:\users\colin\desktop\totte-output"; - private static string outputRoot = @"c:\users\colin\pictures\photos"; + private static string outputRoot = @"c:\users\colin\desktop\totte-output"; + // private static string outputRoot = @"c:\users\colin\pictures\photos"; private static Texture TEXTURE_WHITE = new(new Image(1, 1, new Rgba32(255, 255, 255))); private static Texture TEXTURE_BLACK = new(new Image(1, 1, new Rgba32(0, 0, 0))); @@ -410,8 +410,7 @@ public class Game : GameWindow { int VertexBufferObject; int ElementBufferObject; int VertexArrayObject; - int numThumbnailsLoaded = 0; - readonly object numThumbnailsLoadedLock = new(); + List allPhotos = new(); List photos = new(); HashSet loadedImages = new(); @@ -431,6 +430,15 @@ public class Game : GameWindow { float zoomLevel = 0f; double timeSinceEvent = 0; + // Variables that are protected by locks: + readonly object numThumbnailsLoadedLock = new(); + int numThumbnailsLoaded = 0; + + readonly object exportPhotosLock = new(); // locks the entire ExportPhotos() function. + int numPhotosToExport = 0; + readonly object numPhotosExportedLock = new(); + int numPhotosExported = 0; + protected override void OnUpdateFrame(FrameEventArgs e) { base.OnUpdateFrame(e); toast.Update(e.Time); @@ -684,7 +692,7 @@ public class Game : GameWindow { false, 5 * sizeof(float), 3 * sizeof(float)); // Load photos from a directory. - string[] files = Directory.GetFiles(@"c:\users\colin\desktop\photos-test\"); + // string[] files = Directory.GetFiles(@"c:\users\colin\desktop\photos-test\"); // string[] files = Directory.GetFiles(@"c:\users\colin\pictures\photos\2023\07\14\"); // string[] files = Directory.GetFiles(@"c:\users\colin\pictures\photos\2023\07\23\"); // string[] files = Directory.GetFiles(@"G:\DCIM\100EOSR6\"); @@ -692,7 +700,7 @@ public class Game : GameWindow { // string[] files = Directory.GetFiles(@"c:\users\colin\desktop\import"); // string[] files = Directory.GetFiles(@"C:\Users\colin\Pictures\photos\2018\06\23"); // string[] files = Directory.GetFiles(@"C:\Users\colin\Desktop\Germany all\104D7000"); - // string[] files = Directory.GetFiles(@"C:\Users\colin\Desktop\many-birds\"); + string[] files = Directory.GetFiles(@"C:\Users\colin\Desktop\many-birds\"); for (int i = 0; i < files.Count(); i++) { string file = files[i]; @@ -793,7 +801,7 @@ public class Game : GameWindow { p.LoadThumbnailAsync(geometry.ThumbnailSize); lock (numThumbnailsLoadedLock) { numThumbnailsLoaded++; - toast.Set($"Loading thumbnails: {numThumbnailsLoaded}/{allPhotos.Count}"); + toast.Set($"[{numThumbnailsLoaded}/{allPhotos.Count}] Loading thumbnails"); } })); } @@ -802,13 +810,31 @@ public class Game : GameWindow { // To find the JPEG compression level of a file from the command line: // $ identify -verbose image.jpg | grep Quality: - // FIXME: don't ExportPhotos() if another export is already active. - // FIXME: show a progress bar or something. private async void ExportPhotos() { - JpegEncoder encoder = new JpegEncoder() { Quality = 100 }; - foreach (Photo p in photos) { - await Task.Run( () => { p.SaveAsJpegAsync(outputRoot, encoder); }); + List tasks = new(); + lock (exportPhotosLock) { + // Don't ExportPhotos() if one is already active. + lock (numPhotosExportedLock) { + if (numPhotosToExport > 0 && numPhotosExported != numPhotosToExport) { + Console.WriteLine("ExportPhotos: skipping because another export is already in progress."); + return; + } + } + + JpegEncoder encoder = new JpegEncoder() { Quality = 100 }; + numPhotosToExport = photos.Count; + numPhotosExported = 0; + foreach (Photo p in photos) { + tasks.Add(Task.Run( () => { + p.SaveAsJpegAsync(outputRoot, encoder); + lock (numPhotosExportedLock) { + numPhotosExported++; + toast.Set($"[{numPhotosExported}/{numPhotosToExport}] Exported {outputRoot}/{p.Filename}"); + } + })); + } } + await Task.WhenAll(tasks).ContinueWith(t => { toast.Set("Exporting photos: done!"); }); } protected override void OnRenderFrame(FrameEventArgs e) {