load thumbnails for everything, async'ly on load
This commit is contained in:
parent
cbea050334
commit
50b0e8d8e0
20
Photo.cs
20
Photo.cs
@ -29,12 +29,15 @@ public class Photo {
|
||||
private static long touchCounter = 0;
|
||||
private Texture texture;
|
||||
private Texture placeholder;
|
||||
private Texture thumbnailTexture;
|
||||
private Image<Rgba32>? image = null;
|
||||
private Image<Rgba32>? thumbnail = null;
|
||||
|
||||
public Photo(string filename, Texture placeholder) {
|
||||
Filename = filename;
|
||||
this.placeholder = placeholder;
|
||||
texture = placeholder;
|
||||
thumbnailTexture = placeholder;
|
||||
|
||||
DateTime creationTime = File.GetCreationTime(filename); // Local time.
|
||||
DateTimeOriginal = creationTime;
|
||||
@ -49,12 +52,18 @@ public class Photo {
|
||||
// edit the image due to rotation (etc) and don't want to try generating
|
||||
// a texture for it until that's already happened.
|
||||
LastTouch = touchCounter++;
|
||||
Image<Rgba32> tmp = await Image.LoadAsync<Rgba32>(Filename);
|
||||
Util.RotateImageFromExif(tmp, Orientation);
|
||||
image = tmp;
|
||||
}
|
||||
|
||||
public async void LoadThumbnailAsync() {
|
||||
DecoderOptions options = new DecoderOptions {
|
||||
TargetSize = new Size(256, 256)
|
||||
};
|
||||
Image<Rgba32> tmp = await Image.LoadAsync<Rgba32>(options, Filename);
|
||||
Util.RotateImageFromExif(tmp, Orientation);
|
||||
image = tmp;
|
||||
thumbnail = tmp;
|
||||
}
|
||||
|
||||
public void Unload() {
|
||||
@ -273,16 +282,21 @@ public class Photo {
|
||||
|
||||
public Texture Texture() {
|
||||
LastTouch = touchCounter++;
|
||||
if (thumbnailTexture == placeholder && thumbnail != null) {
|
||||
thumbnailTexture = new(thumbnail);
|
||||
thumbnail.Dispose();
|
||||
thumbnail = null;
|
||||
}
|
||||
if (texture == placeholder && image != null) {
|
||||
// The texture needs to be created on the GL thread, so we instantiate
|
||||
// it here (since this is called from OnRenderFrame), as long as the
|
||||
// image is ready to go.
|
||||
texture = new Texture(image);
|
||||
texture = new(image);
|
||||
image.Dispose();
|
||||
image = null;
|
||||
Loaded = true;
|
||||
}
|
||||
return texture;
|
||||
return texture != placeholder ? texture : thumbnailTexture;
|
||||
}
|
||||
|
||||
public string Description() {
|
||||
|
23
Program.cs
23
Program.cs
@ -652,6 +652,8 @@ public class Game : GameWindow {
|
||||
|
||||
allPhotos.Sort(ComparePhotosByDate);
|
||||
photos = allPhotos;
|
||||
|
||||
LoadThumbnailsAsync();
|
||||
}
|
||||
|
||||
private static int ComparePhotosByDate(Photo x, Photo y) {
|
||||
@ -669,11 +671,9 @@ public class Game : GameWindow {
|
||||
}
|
||||
|
||||
private void UnloadImages() {
|
||||
return;
|
||||
// Unload images that haven't been touched in a while.
|
||||
// FIXME: keep around thumbnail-sized textures?
|
||||
lock (loadedImagesLock) {
|
||||
while (loadedImages.Count > 100) {
|
||||
while (loadedImages.Count > 30) {
|
||||
long earliestTime = long.MaxValue;
|
||||
Photo? earliest = null;
|
||||
foreach (Photo photo in loadedImages) {
|
||||
@ -704,9 +704,8 @@ public class Game : GameWindow {
|
||||
}
|
||||
}
|
||||
// Start loading any images that are in our window but not yet loaded.
|
||||
int minLoadedImage = Math.Max(0, photoIndex - 30);
|
||||
// int maxLoadedImage = Math.Min(photoIndex + 30, photos.Count - 1);
|
||||
int maxLoadedImage = photos.Count - 1;
|
||||
int minLoadedImage = Math.Max(0, photoIndex - 10);
|
||||
int maxLoadedImage = Math.Min(photoIndex + 10, photos.Count - 1);
|
||||
List<Photo> toLoad = new();
|
||||
for (int i = minLoadedImage; i <= maxLoadedImage; i++) {
|
||||
lock (loadedImagesLock) {
|
||||
@ -722,6 +721,12 @@ public class Game : GameWindow {
|
||||
}
|
||||
}
|
||||
|
||||
private async void LoadThumbnailsAsync() {
|
||||
foreach (Photo p in allPhotos) {
|
||||
await Task.Run( () => { p.LoadThumbnailAsync(); });
|
||||
}
|
||||
}
|
||||
|
||||
// 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.
|
||||
@ -988,9 +993,9 @@ static class Program {
|
||||
nwSettings.CurrentMonitor = bestMonitor.Handle;
|
||||
nwSettings.Location = new Vector2i(bestMonitor.WorkArea.Min.X + 1,
|
||||
bestMonitor.WorkArea.Min.Y + 31);
|
||||
// nwSettings.Size = new Vector2i(bestMonitor.WorkArea.Size.X - 2,
|
||||
// bestMonitor.WorkArea.Size.Y - 32);
|
||||
nwSettings.Size = new Vector2i(1600, 900);
|
||||
nwSettings.Size = new Vector2i(bestMonitor.WorkArea.Size.X - 2,
|
||||
bestMonitor.WorkArea.Size.Y - 32);
|
||||
// nwSettings.Size = new Vector2i(1600, 900);
|
||||
nwSettings.MinimumSize = UiGeometry.MIN_WINDOW_SIZE;
|
||||
nwSettings.Title = "Totte";
|
||||
nwSettings.IsEventDriven = true;
|
||||
|
Loading…
Reference in New Issue
Block a user