|
|
@ -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<Rgba32>(1, 1, new Rgba32(255, 255, 255))); |
|
|
|
private static Texture TEXTURE_BLACK = new(new Image<Rgba32>(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<Photo> allPhotos = new(); |
|
|
|
List<Photo> photos = new(); |
|
|
|
HashSet<Photo> 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<Task> 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) { |
|
|
|