start to load images async

This commit is contained in:
Colin McMillen 2023-07-16 23:45:50 -04:00
parent 693269b8f5
commit faee485b5c

View File

@ -139,20 +139,14 @@ void main() {
} }
public class Photo { public class Photo {
public Texture Texture; private Texture texture;
public bool Loaded = false; private Texture placeholder;
private readonly string filename; private Image<Rgba32> image;
public Photo(string filename, Texture unloadedTexture) { public Photo(Image<Rgba32> image, Texture placeholder) {
this.filename = filename; this.image = image;
Texture = unloadedTexture; this.placeholder = placeholder;
} texture = placeholder;
public void Load() {
Image<Rgba32> image = Image.Load<Rgba32>(filename);
Console.WriteLine("----------------------------------");
Console.WriteLine($"image loaded: {image.Width}x{image.Height}");
ExifProfile? exifs = image.Metadata.ExifProfile; ExifProfile? exifs = image.Metadata.ExifProfile;
if (exifs != null) { if (exifs != null) {
@ -162,9 +156,15 @@ public class Photo {
} }
} }
} }
Texture = new Texture(image);
Loaded = true;
} }
public Texture Texture() {
if (texture == placeholder) {
texture = new Texture(image);
image.Dispose();
}
return texture;
}
} }
public class Texture : IDisposable { public class Texture : IDisposable {
@ -175,7 +175,6 @@ public class Texture : IDisposable {
Size = new Vector2i(image.Width, image.Height); Size = new Vector2i(image.Width, image.Height);
byte[] pixelBytes = new byte[Size.X * Size.Y * Unsafe.SizeOf<Rgba32>()]; byte[] pixelBytes = new byte[Size.X * Size.Y * Unsafe.SizeOf<Rgba32>()];
image.CopyPixelDataTo(pixelBytes); image.CopyPixelDataTo(pixelBytes);
image.Dispose();
Handle = GL.GenTexture(); Handle = GL.GenTexture();
GL.ActiveTexture(TextureUnit.Texture0); GL.ActiveTexture(TextureUnit.Texture0);
@ -262,6 +261,7 @@ public class Game : GameWindow {
1, 2, 3 // second triangle 1, 2, 3 // second triangle
}; };
bool doneLoading = false;
int VertexBufferObject; int VertexBufferObject;
int ElementBufferObject; int ElementBufferObject;
int VertexArrayObject; int VertexArrayObject;
@ -293,7 +293,6 @@ public class Game : GameWindow {
} }
} }
// Track keyboard repeat times for advancing up/down. // Track keyboard repeat times for advancing up/down.
if (!input.IsKeyDown(Keys.Down)) { if (!input.IsKeyDown(Keys.Down)) {
downTimer = Int64.MaxValue; downTimer = Int64.MaxValue;
@ -318,7 +317,7 @@ public class Game : GameWindow {
} }
} }
protected override void OnLoad() { protected override async void OnLoad() {
base.OnLoad(); base.OnLoad();
GL.ClearColor(0f, 0f, 0f, 1f); GL.ClearColor(0f, 0f, 0f, 1f);
@ -354,19 +353,24 @@ public class Game : GameWindow {
// Load textures from JPEGs. // Load textures from JPEGs.
// 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\14\");
//string[] files = Directory.GetFiles(@"C:\Users\colin\Pictures\photos\2018\06\23");
List<Task<Image<Rgba32>>> imageTasks = new();
for (int i = 0; i < files.Count(); i++) { for (int i = 0; i < files.Count(); i++) {
string file = files[i]; string file = files[i];
if (file.ToLower().EndsWith(".jpg")) { if (file.ToLower().EndsWith(".jpg")) {
Photo photo = new(file, TEXTURE_WHITE); imageTasks.Add(Image.LoadAsync<Rgba32>(file));
if (i == 0) {
photo.Load();
}
photos.Add(photo);
if (photos.Count > 10) {
break;
}
} }
} }
Console.WriteLine(DateTime.Now);
await Task.WhenAll(imageTasks);
Console.WriteLine(DateTime.Now);
foreach (Task<Image<Rgba32>> task in imageTasks) {
Photo photo = new(task.Result, TEXTURE_WHITE);
photos.Add(photo);
}
doneLoading = true;
} }
protected override void OnUnload() { protected override void OnUnload() {
@ -375,11 +379,15 @@ public class Game : GameWindow {
protected override void OnRenderFrame(FrameEventArgs e) { protected override void OnRenderFrame(FrameEventArgs e) {
base.OnRenderFrame(e); base.OnRenderFrame(e);
if (!doneLoading) {
return;
}
GL.Clear(ClearBufferMask.ColorBufferBit); GL.Clear(ClearBufferMask.ColorBufferBit);
GL.BindBuffer(BufferTarget.ArrayBuffer, VertexBufferObject); GL.BindBuffer(BufferTarget.ArrayBuffer, VertexBufferObject);
GL.ActiveTexture(TextureUnit.Texture0); GL.ActiveTexture(TextureUnit.Texture0);
Texture active = photos[photoIndex].Texture; Texture active = photos[photoIndex].Texture();
// FIXME: make a function for scaling & centering one box on another. // FIXME: make a function for scaling & centering one box on another.
float scaleX = 1f * geometry.PhotoBox.Size.X / active.Size.X; float scaleX = 1f * geometry.PhotoBox.Size.X / active.Size.X;
@ -390,9 +398,9 @@ public class Game : GameWindow {
Vector2i center = (Vector2i) geometry.PhotoBox.Center; Vector2i center = (Vector2i) geometry.PhotoBox.Center;
Box2i photoBox = Util.makeBox(center.X - renderSize.X / 2, center.Y - renderSize.Y / 2, renderSize.X, renderSize.Y); Box2i photoBox = Util.makeBox(center.X - renderSize.X / 2, center.Y - renderSize.Y / 2, renderSize.X, renderSize.Y);
DrawTexture(active, photoBox); DrawTexture(active, photoBox);
for (int i = 0; i < photos.Count; i++) { for (int i = 0; i < photos.Count && i < geometry.ThumbnailBoxes.Count(); i++) {
Box2i box = geometry.ThumbnailBoxes[i]; Box2i box = geometry.ThumbnailBoxes[i];
DrawTexture(photos[i].Texture, box); DrawTexture(photos[i].Texture(), box);
if (i == photoIndex) { if (i == photoIndex) {
DrawBox(box, 5, Color4.Black); DrawBox(box, 5, Color4.Black);
DrawBox(box, 3, Color4.White); DrawBox(box, 3, Color4.White);
@ -402,7 +410,6 @@ public class Game : GameWindow {
SwapBuffers(); SwapBuffers();
} }
// FIXME: pull these out into a Util class and let photos be able to draw themselves?
void DrawTexture(Texture texture, Box2i box) { void DrawTexture(Texture texture, Box2i box) {
DrawTexture(texture, box, Color4.White); DrawTexture(texture, box, Color4.White);
} }