|
|
@ -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<Photo> photos = new(); |
|
|
|
HashSet<int> 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<int> loadedImages = new(); |
|
|
|
GL.ActiveTexture(TextureUnit.Texture0); |
|
|
|
|
|
|
|
Photo activePhoto = photos[photoIndex]; |
|
|
@ -829,4 +854,3 @@ static class Program { |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
|