From 27a4a64ccb5447ad9596ad8e93af47ac88d58122 Mon Sep 17 00:00:00 2001 From: Colin McMillen Date: Tue, 25 Jul 2023 21:24:20 -0400 Subject: [PATCH] load and unload images dynamically --- Program.cs | 54 +++++++++++++++++++++++++++++++++++++++--------------- 1 file changed, 39 insertions(+), 15 deletions(-) diff --git a/Program.cs b/Program.cs index c8c519d..cf7a758 100644 --- a/Program.cs +++ b/Program.cs @@ -177,7 +177,7 @@ public class Photo { TryParseRating(info.Metadata.XmpProfile, out Rating); } - public async void Load() { + public async void LoadAsync() { // We don't assign to this.image until Load() is done, because we might // edit the image due to rotation (etc) and don't want to try generating // a texture for it until that's already happened. @@ -186,6 +186,13 @@ public class Photo { image = tmp; } + public void Unload() { + if (texture != placeholder) { + texture.Dispose(); + texture = placeholder; + } + } + private bool TryParseRating(XmpProfile? xmp, out int rating) { rating = 0; if (xmp == null) { @@ -320,10 +327,6 @@ public class Photo { Console.WriteLine($"*** WARNING: unexpected DateTimeOriginal value: {dateTimeOriginal.Value}"); } } - - // foreach (IExifValue exif in exifs.Values) { - // Console.WriteLine(exif.Tag.ToString() + " " + exif.GetValue().ToString()); - // } } public Texture Texture() { @@ -512,6 +515,7 @@ public class Game : GameWindow { int ElementBufferObject; int VertexArrayObject; List photos = new(); + HashSet loadedImages = new(); int photoIndex = 0; int ribbonIndex = 0; Shader shader = new(); @@ -606,7 +610,7 @@ public class Game : GameWindow { } } - protected override async void OnLoad() { + protected override void OnLoad() { base.OnLoad(); GL.ClearColor(0f, 0f, 0f, 1f); @@ -642,12 +646,12 @@ public class Game : GameWindow { GL.EnableVertexAttribArray(texCoordLocation); GL.VertexAttribPointer(texCoordLocation, 2, VertexAttribPointerType.Float, false, 5 * sizeof(float), 3 * sizeof(float)); - // Load textures from JPEGs. + // Load photos from a directory. // 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(@"G:\DCIM\100EOSR6\"); + // string[] files = Directory.GetFiles(@"G:\DCIM\100EOSR6\"); // 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\Germany all\104D7000"); // string[] files = Directory.GetFiles(@"C:\Users\colin\Desktop\many-birds\"); for (int i = 0; i < files.Count(); i++) { @@ -659,10 +663,6 @@ public class Game : GameWindow { } photos.Sort(ComparePhotosByDate); - - for (int i = 0; i < 40 && i < photos.Count; i++) { - await Task.Run( () => { photos[i].Load(); }); - } } private static int ComparePhotosByDate(Photo x, Photo y) { @@ -679,11 +679,36 @@ public class Game : GameWindow { base.OnUnload(); } + private async void LoadAndUnloadImagesAsync() { + int minUnloadedImage = Math.Max(0, photoIndex - 40); + int maxUnloadedImage = Math.Min(photoIndex + 40, photos.Count - 1); + int minLoadedImage = Math.Max(0, photoIndex - 20); + int maxLoadedImage = Math.Min(photoIndex + 20, photos.Count - 1); + // First, unload images that are far outside our window. + foreach (int i in loadedImages) { + if (i < minUnloadedImage || i > maxUnloadedImage) { + loadedImages.Remove(i); + photos[i].Unload(); + Console.WriteLine("unloading " + i); + } + } + // Then, start loading any images that aren't in our window. + for (int i = minLoadedImage; i <= maxLoadedImage; i++) { + if (!loadedImages.Contains(i)) { + Console.WriteLine("loading " + i); + loadedImages.Add(i); + await Task.Run( () => { photos[i].LoadAsync(); }); + } + } + } + protected override void OnRenderFrame(FrameEventArgs e) { base.OnRenderFrame(e); + LoadAndUnloadImagesAsync(); + GL.Clear(ClearBufferMask.ColorBufferBit); - GL.BindBuffer(BufferTarget.ArrayBuffer, VertexBufferObject); + GL.BindBuffer(BufferTarget.ArrayBuffer, VertexBufferObject); HashSet loadedImages = new(); GL.ActiveTexture(TextureUnit.Texture0); Photo activePhoto = photos[photoIndex]; @@ -829,4 +854,3 @@ static class Program { } } } -