Skip to content

Commit

Permalink
fixed: cached thumbnail is not updated when replacing image with same…
Browse files Browse the repository at this point in the history
… name

#1564, #1859, #1922
  • Loading branch information
d2phap committed May 29, 2024
1 parent a82c863 commit ad04356
Show file tree
Hide file tree
Showing 10 changed files with 75 additions and 74 deletions.
47 changes: 24 additions & 23 deletions Source/Components/ImageGlass.Gallery/Cache/ThumbnailCacheManager.cs
Original file line number Diff line number Diff line change
Expand Up @@ -101,7 +101,7 @@ private class CacheRequest
/// <summary>
/// Gets the public key for the virtual item.
/// </summary>
public object VirtualItemKey { get; private set; }
public string VirtualKey { get; private set; }
/// <summary>
/// Gets the size of the requested thumbnail.
/// </summary>
Expand All @@ -125,15 +125,15 @@ private class CacheRequest
/// </summary>
/// <param name="guid">The guid of the <see cref="ImageGalleryItem"/>.</param>
/// <param name="adaptor">The adaptor of this item.</param>
/// <param name="key">The public key for the virtual item.</param>
/// <param name="filePath">The file path for item.</param>
/// <param name="size">The size of the requested thumbnail.</param>
/// <param name="useEmbeddedThumbnails">UseEmbeddedThumbnails property of the owner control.</param>
/// <param name="autoRotate">AutoRotate property of the owner control.</param>
/// <param name="requestType">Type of this request.</param>
public CacheRequest(Guid guid, IAdaptor adaptor, object key, Size size, UseEmbeddedThumbnails useEmbeddedThumbnails, bool autoRotate, RequestType requestType)
public CacheRequest(Guid guid, IAdaptor adaptor, string filePath, Size size, UseEmbeddedThumbnails useEmbeddedThumbnails, bool autoRotate, RequestType requestType)
{
Guid = guid;
VirtualItemKey = key;
VirtualKey = filePath;
Adaptor = adaptor;
Size = size;
UseEmbeddedThumbnails = useEmbeddedThumbnails;
Expand All @@ -146,7 +146,7 @@ public CacheRequest(Guid guid, IAdaptor adaptor, object key, Size size, UseEmbed
/// </summary>
public override string ToString()
{
return "CacheRequest (" + VirtualItemKey.ToString() + ")";
return "CacheRequest (" + VirtualKey.ToString() + ")";
}
}
#endregion
Expand Down Expand Up @@ -512,7 +512,7 @@ private void Bw_DoWork(object? sender, QueuedWorkerDoWorkEventArgs e)
}

Image? thumb = null;
var diskCacheKey = request.Adaptor.GetUniqueIdentifier(request.VirtualItemKey, request.Size, request.UseEmbeddedThumbnails, request.AutoRotate);
var diskCacheKey = request.Adaptor.GetUniqueIdentifier(request.VirtualKey, request.Size, request.UseEmbeddedThumbnails, request.AutoRotate);

// Check the disk cache
using var cs = _diskCache.Read(diskCacheKey);
Expand All @@ -527,7 +527,7 @@ private void Bw_DoWork(object? sender, QueuedWorkerDoWorkEventArgs e)
{
try
{
thumb = request.Adaptor.GetThumbnail(request.VirtualItemKey, request.Size, request.UseEmbeddedThumbnails, request.AutoRotate);
thumb = request.Adaptor.GetThumbnail(request.VirtualKey, request.Size, request.UseEmbeddedThumbnails, request.AutoRotate);
}
// fix infinite re-cache when throwing error
catch { }
Expand Down Expand Up @@ -694,7 +694,7 @@ public void Remove(Guid guid, bool removeNow)
if (item != null)
{
var diskCacheKey = item.Adaptor.GetUniqueIdentifier(
item.VirtualItemKey,
item.VirtualKey,
cacheItem.Size,
cacheItem.UseEmbeddedThumbnails,
cacheItem.AutoRotate);
Expand Down Expand Up @@ -820,11 +820,11 @@ private static int GetImageMemorySize(int width, int height)
/// </summary>
/// <param name="guid">The guid representing this item.</param>
/// <param name="adaptor">he adaptor for this item.</param>
/// <param name="key">The key of this item.</param>
/// <param name="filePath">The file path of this item.</param>
/// <param name="thumbSize">Requested thumbnail size.</param>
/// <param name="useEmbeddedThumbnails">UseEmbeddedThumbnails property of the owner control.</param>
/// <param name="autoRotate">AutoRotate property of the owner control.</param>
public void Add(Guid guid, IAdaptor adaptor, object key, Size thumbSize, UseEmbeddedThumbnails useEmbeddedThumbnails, bool autoRotate)
public void Add(Guid guid, IAdaptor adaptor, string filePath, Size thumbSize, UseEmbeddedThumbnails useEmbeddedThumbnails, bool autoRotate)
{
// Already cached?
if (_thumbCache.TryGetValue(guid, out CacheItem? item))
Expand All @@ -834,20 +834,20 @@ public void Add(Guid guid, IAdaptor adaptor, object key, Size thumbSize, UseEmbe
}

// Add to cache queue
RunWorker(new CacheRequest(guid, adaptor, key, thumbSize, useEmbeddedThumbnails, autoRotate, RequestType.Thumbnail));
RunWorker(new CacheRequest(guid, adaptor, filePath, thumbSize, useEmbeddedThumbnails, autoRotate, RequestType.Thumbnail));
}

/// <summary>
/// Adds a virtual item to the cache.
/// </summary>
/// <param name="guid">The guid representing this item.</param>
/// <param name="adaptor">The adaptor for this item.</param>
/// <param name="key">The key of this item.</param>
/// <param name="filePath">The file path of this item.</param>
/// <param name="thumbSize">Requested thumbnail size.</param>
/// <param name="thumb">Thumbnail image to add to cache.</param>
/// <param name="useEmbeddedThumbnails">UseEmbeddedThumbnails property of the owner control.</param>
/// <param name="autoRotate">AutoRotate property of the owner control.</param>
public void Add(Guid guid, IAdaptor adaptor, object key, Size thumbSize, Image? thumb, UseEmbeddedThumbnails useEmbeddedThumbnails, bool autoRotate)
public void Add(Guid guid, IAdaptor adaptor, string filePath, Size thumbSize, Image? thumb, UseEmbeddedThumbnails useEmbeddedThumbnails, bool autoRotate)
{
// Already cached?
if (_thumbCache.TryGetValue(guid, out CacheItem? item))
Expand All @@ -864,7 +864,7 @@ public void Add(Guid guid, IAdaptor adaptor, object key, Size thumbSize, Image?

// Add to disk cache
using var stream = new MemoryStream();
var diskCacheKey = adaptor.GetUniqueIdentifier(key, thumbSize, useEmbeddedThumbnails, autoRotate);
var diskCacheKey = adaptor.GetUniqueIdentifier(filePath, thumbSize, useEmbeddedThumbnails, autoRotate);
thumb.Save(stream, System.Drawing.Imaging.ImageFormat.Png);
_diskCache.Write(diskCacheKey, stream);

Expand All @@ -882,11 +882,11 @@ public void Add(Guid guid, IAdaptor adaptor, object key, Size thumbSize, Image?
/// </summary>
/// <param name="guid">The guid representing this item.</param>
/// <param name="adaptor">The adaptor for this item.</param>
/// <param name="key">The key of this item.</param>
/// <param name="filePath">The file path of this item.</param>
/// <param name="thumbSize">Requested thumbnail size.</param>
/// <param name="useEmbeddedThumbnails">UseEmbeddedThumbnails property of the owner control.</param>
/// <param name="autoRotate">AutoRotate property of the owner control.</param>
public void AddToGalleryCache(Guid guid, IAdaptor adaptor, object key, Size thumbSize, UseEmbeddedThumbnails useEmbeddedThumbnails, bool autoRotate)
public void AddToGalleryCache(Guid guid, IAdaptor adaptor, string filePath, Size thumbSize, UseEmbeddedThumbnails useEmbeddedThumbnails, bool autoRotate)
{
// Already cached?
if (_galleryItem != null
Expand All @@ -898,19 +898,19 @@ public void AddToGalleryCache(Guid guid, IAdaptor adaptor, object key, Size thum
return;

// Add to cache queue
RunWorker(new CacheRequest(guid, adaptor, key, thumbSize, useEmbeddedThumbnails, autoRotate, RequestType.Gallery), 2);
RunWorker(new CacheRequest(guid, adaptor, filePath, thumbSize, useEmbeddedThumbnails, autoRotate, RequestType.Gallery), 2);
}

/// <summary>
/// Adds the virtual item image to the renderer cache queue.
/// </summary>
/// <param name="guid">The guid representing this item.</param>
/// <param name="adaptor">The adaptor of this item.</param>
/// <param name="key">The key of this item.</param>
/// <param name="filePath">The file path of this item.</param>
/// <param name="thumbSize">Requested thumbnail size.</param>
/// <param name="useEmbeddedThumbnails">UseEmbeddedThumbnails property of the owner control.</param>
/// <param name="autoRotate">AutoRotate property of the owner control.</param>
public void AddToRendererCache(Guid guid, IAdaptor adaptor, object key, Size thumbSize, UseEmbeddedThumbnails useEmbeddedThumbnails, bool autoRotate)
public void AddToRendererCache(Guid guid, IAdaptor adaptor, string filePath, Size thumbSize, UseEmbeddedThumbnails useEmbeddedThumbnails, bool autoRotate)
{
// Already cached?
if (_rendererItem != null
Expand All @@ -922,7 +922,7 @@ public void AddToRendererCache(Guid guid, IAdaptor adaptor, object key, Size thu
return;

// Add to cache queue
RunWorker(new CacheRequest(guid, adaptor, key, thumbSize, useEmbeddedThumbnails, autoRotate, RequestType.Renderer), 1);
RunWorker(new CacheRequest(guid, adaptor, filePath, thumbSize, useEmbeddedThumbnails, autoRotate, RequestType.Renderer), 1);
}

/// <summary>
Expand Down Expand Up @@ -973,12 +973,12 @@ public void AddToRendererCache(Guid guid, IAdaptor adaptor, object key, Size thu
/// </summary>
/// <param name="guid">The guid representing this item.</param>
/// <param name="adaptor">The adaptor of this item.</param>
/// <param name="key">The key of this item.</param>
/// <param name="filePath">The key of this item.</param>
/// <param name="thumbSize">Requested thumbnail size.</param>
/// <param name="useEmbeddedThumbnails">UseEmbeddedThumbnails property of the owner control.</param>
/// <param name="autoRotate">AutoRotate property of the owner control.</param>
/// <param name="clone">true to return a clone of the cached image; otherwise false.</param>
public Image? GetImage(Guid guid, IAdaptor adaptor, object key, Size thumbSize, UseEmbeddedThumbnails useEmbeddedThumbnails, bool autoRotate, bool clone)
public Image? GetImage(Guid guid, IAdaptor adaptor, string filePath, Size thumbSize, UseEmbeddedThumbnails useEmbeddedThumbnails, bool autoRotate, bool clone)
{
if (_thumbCache.TryGetValue(guid, out CacheItem? item)
&& item != null
Expand All @@ -998,7 +998,8 @@ public void AddToRendererCache(Guid guid, IAdaptor adaptor, object key, Size thu
}
else
{
var diskCacheKey = adaptor.GetUniqueIdentifier(key, thumbSize, useEmbeddedThumbnails, autoRotate);
var fi = new FileInfo(filePath.ToString());
var diskCacheKey = adaptor.GetUniqueIdentifier(filePath, thumbSize, useEmbeddedThumbnails, autoRotate);

// Check the disk cache
using var stream = _diskCache.Read(diskCacheKey);
Expand Down
2 changes: 1 addition & 1 deletion Source/Components/ImageGlass.Gallery/ImageGallery.cs
Original file line number Diff line number Diff line change
Expand Up @@ -1049,7 +1049,7 @@ public void ClearThumbnailCache()
{
foreach (ImageGalleryItem item in mItems)
{
thumbnailCache.Add(item.Guid, item.Adaptor, item.VirtualItemKey, mThumbnailSize, mUseEmbeddedThumbnails, AutoRotateThumbnails);
thumbnailCache.Add(item.Guid, item.Adaptor, item.VirtualKey, mThumbnailSize, mUseEmbeddedThumbnails, AutoRotateThumbnails);
}
}
Refresh();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -53,16 +53,14 @@ public FileSystemAdaptor() { }
/// <param name="useEmbeddedThumbnails">Embedded thumbnail usage.</param>
/// <param name="useExifOrientation">true to automatically rotate images based on Exif orientation; otherwise false.</param>
/// <returns>The thumbnail image from the given item or null if an error occurs.</returns>
public override Image? GetThumbnail(object key, Size size, UseEmbeddedThumbnails useEmbeddedThumbnails, bool useExifOrientation)
public override Image? GetThumbnail(string filePath, Size size, UseEmbeddedThumbnails useEmbeddedThumbnails, bool useExifOrientation)
{
if (_isDisposed) return null;


try
{
var filename = (string)key;

return Extractor.Current.GetThumbnail(filename, size, useEmbeddedThumbnails, useExifOrientation);
return Extractor.Current.GetThumbnail(filePath, size, useEmbeddedThumbnails, useExifOrientation);
}
catch (Exception)
{
Expand All @@ -79,10 +77,14 @@ public FileSystemAdaptor() { }
/// <param name="useEmbeddedThumbnails">Embedded thumbnail usage.</param>
/// <param name="useExifOrientation">true to automatically rotate images based on Exif orientation; otherwise false.</param>
/// <returns>A unique identifier string for the thumnail.</returns>
public override string GetUniqueIdentifier(object key, Size size, UseEmbeddedThumbnails useEmbeddedThumbnails, bool useExifOrientation)
public override string GetUniqueIdentifier(string filePath, Size size, UseEmbeddedThumbnails useEmbeddedThumbnails, bool useExifOrientation)
{
var fi = new FileInfo(filePath);
using var sb = ZString.CreateStringBuilder();
sb.Append((string)key); // Filename

sb.Append(filePath);
sb.Append(':');
sb.Append(fi.LastWriteTimeUtc.ToBinary());
sb.Append(':');
sb.Append(size.Width); // Thumbnail size
sb.Append(',');
Expand All @@ -100,24 +102,22 @@ public override string GetUniqueIdentifier(object key, Size size, UseEmbeddedThu
/// </summary>
/// <param name="key">Item key.</param>
/// <returns>The path to the source image.</returns>
public override string GetSourceImage(object key)
public override string GetSourceImage(string filePath)
{
if (_isDisposed) return string.Empty;

return (string)key;
return filePath;
}

/// <summary>
/// Returns the details for the given item.
/// </summary>
/// <param name="key">Item key.</param>
/// <returns>An array of tuples containing item details or null if an error occurs.</returns>
public override IgMetadata GetDetails(object key)
public override IgMetadata GetDetails(string filePath)
{
if (_isDisposed) return new IgMetadata();

var filePath = (string)key;

return PhotoCodec.LoadMetadata(filePath);
}

Expand Down
16 changes: 8 additions & 8 deletions Source/Components/ImageGlass.Gallery/Item/Adaptor/IAdaptor.cs
Original file line number Diff line number Diff line change
Expand Up @@ -37,36 +37,36 @@ public abstract class IAdaptor : IDisposable
/// <summary>
/// Returns the thumbnail image for the given item.
/// </summary>
/// <param name="key">Item key.</param>
/// <param name="filePath">Item file path.</param>
/// <param name="size">Requested image size.</param>
/// <param name="useEmbeddedThumbnails">Embedded thumbnail usage.</param>
/// <param name="useExifOrientation">true to automatically rotate images based on Exif orientation; otherwise false.</param>
/// <returns>The thumbnail image from the given item or null if an error occurs.</returns>
public abstract Image? GetThumbnail(object key, Size size, UseEmbeddedThumbnails useEmbeddedThumbnails, bool useExifOrientation);
public abstract Image? GetThumbnail(string filePath, Size size, UseEmbeddedThumbnails useEmbeddedThumbnails, bool useExifOrientation);

/// <summary>
/// Returns a unique identifier for this thumbnail to be used in persistent
/// caching.
/// </summary>
/// <param name="key">Item key.</param>
/// <param name="filePath">Item file path.</param>
/// <param name="size">Requested image size.</param>
/// <param name="useEmbeddedThumbnails">Embedded thumbnail usage.</param>
/// <param name="useExifOrientation">true to automatically rotate images based on Exif orientation; otherwise false.</param>
/// <returns>A unique identifier string for the thumnail.</returns>
public abstract string GetUniqueIdentifier(object key, Size size, UseEmbeddedThumbnails useEmbeddedThumbnails, bool useExifOrientation);
public abstract string GetUniqueIdentifier(string filePath, Size size, UseEmbeddedThumbnails useEmbeddedThumbnails, bool useExifOrientation);

/// <summary>
/// Returns the path to the source image for use in drag operations.
/// </summary>
/// <param name="key">Item key.</param>
/// <param name="filePath">Item file path.</param>
/// <returns>The path to the source image.</returns>
public abstract string GetSourceImage(object key);
public abstract string GetSourceImage(string filePath);

/// <summary>
/// Returns the details for the given item.
/// </summary>
/// <param name="key">Item key.</param>
public abstract IgMetadata GetDetails(object key);
/// <param name="filePath">Item file path.</param>
public abstract IgMetadata GetDetails(string filePath);

/// <summary>
/// Performs application-defined tasks associated with freeing,
Expand Down
Loading

0 comments on commit ad04356

Please sign in to comment.