mirror of
https://github.com/cyanfish/naps2.git
synced 2024-10-04 11:27:08 +03:00
Add thumbnail cache to improve performance and make lifetime management easier
This commit is contained in:
parent
49d7e54d30
commit
4ac72ef8db
@ -91,6 +91,7 @@
|
||||
<Compile Include="Scan\Batch\BatchScanPerformer.cs" />
|
||||
<Compile Include="Scan\Batch\BatchSettings.cs" />
|
||||
<Compile Include="Scan\Exceptions\NoDuplexSupportException.cs" />
|
||||
<Compile Include="Scan\Images\ThumbnailCache.cs" />
|
||||
<Compile Include="Scan\Images\Transforms\TrueContrastTransform.cs" />
|
||||
<Compile Include="Scan\PatchCode.cs" />
|
||||
<Compile Include="Scan\ProfileNameTracker.cs" />
|
||||
|
82
NAPS2.Core/Scan/Images/ThumbnailCache.cs
Normal file
82
NAPS2.Core/Scan/Images/ThumbnailCache.cs
Normal file
@ -0,0 +1,82 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Drawing;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using NAPS2.Config;
|
||||
|
||||
namespace NAPS2.Scan.Images
|
||||
{
|
||||
public class ThumbnailCache : IDisposable
|
||||
{
|
||||
private readonly Dictionary<ScannedImage, CacheItem> cache = new Dictionary<ScannedImage,CacheItem>();
|
||||
|
||||
private readonly IUserConfigManager userConfigManager;
|
||||
|
||||
public ThumbnailCache(IUserConfigManager userConfigManager)
|
||||
{
|
||||
this.userConfigManager = userConfigManager;
|
||||
}
|
||||
|
||||
~ThumbnailCache()
|
||||
{
|
||||
Dispose();
|
||||
}
|
||||
|
||||
public void Dispose()
|
||||
{
|
||||
foreach (var item in cache.Values)
|
||||
{
|
||||
item.Thumbnail.Dispose();
|
||||
}
|
||||
cache.Clear();
|
||||
}
|
||||
|
||||
public Bitmap this[ScannedImage scannedImage]
|
||||
{
|
||||
get
|
||||
{
|
||||
var newState = scannedImage.GetThumbnailState();
|
||||
if (cache.ContainsKey(scannedImage))
|
||||
{
|
||||
// Cache hit
|
||||
var item = cache[scannedImage];
|
||||
if (item.State != newState)
|
||||
{
|
||||
// Invalidated
|
||||
item.Thumbnail.Dispose();
|
||||
item.Thumbnail = scannedImage.GetThumbnail(userConfigManager.Config.ThumbnailSize);
|
||||
item.State = newState;
|
||||
}
|
||||
return item.Thumbnail;
|
||||
}
|
||||
else
|
||||
{
|
||||
// Cache miss
|
||||
var item = new CacheItem
|
||||
{
|
||||
Thumbnail = scannedImage.GetThumbnail(userConfigManager.Config.ThumbnailSize),
|
||||
State = newState
|
||||
};
|
||||
return item.Thumbnail;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public void TrimCache(IEnumerable<ScannedImage> currentImages)
|
||||
{
|
||||
foreach (var key in cache.Keys.Except(currentImages).ToList())
|
||||
{
|
||||
cache[key].Thumbnail.Dispose();
|
||||
cache.Remove(key);
|
||||
}
|
||||
}
|
||||
|
||||
private class CacheItem
|
||||
{
|
||||
public Bitmap Thumbnail { get; set; }
|
||||
|
||||
public object State { get; set; }
|
||||
}
|
||||
}
|
||||
}
|
@ -1546,7 +1546,7 @@ namespace NAPS2.WinForms
|
||||
int index = imageList.Images.IndexOf(img);
|
||||
if (index != -1)
|
||||
{
|
||||
thumbnailList1.ReplaceThumbnail(index, thumbnail);
|
||||
thumbnailList1.ReplaceThumbnail(index, img);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
@ -30,13 +30,21 @@ namespace NAPS2.WinForms
|
||||
{
|
||||
public partial class ThumbnailList : ListView
|
||||
{
|
||||
private ThumbnailCache thumbnails;
|
||||
|
||||
public ThumbnailList()
|
||||
{
|
||||
InitializeComponent();
|
||||
LargeImageList = ilThumbnailList;
|
||||
}
|
||||
|
||||
public IUserConfigManager UserConfigManager { get; set; }
|
||||
public IUserConfigManager UserConfigManager
|
||||
{
|
||||
set
|
||||
{
|
||||
thumbnails = new ThumbnailCache(value);
|
||||
}
|
||||
}
|
||||
|
||||
public Size ThumbnailSize
|
||||
{
|
||||
@ -46,46 +54,31 @@ namespace NAPS2.WinForms
|
||||
|
||||
public void UpdateImages(List<ScannedImage> images)
|
||||
{
|
||||
ClearImages();
|
||||
ilThumbnailList.Images.Clear();
|
||||
Clear();
|
||||
foreach (ScannedImage img in images)
|
||||
{
|
||||
AppendImage(img);
|
||||
}
|
||||
thumbnails.TrimCache(images);
|
||||
}
|
||||
|
||||
public void AppendImage(ScannedImage img)
|
||||
{
|
||||
ilThumbnailList.Images.Add(img.GetThumbnail(UserConfigManager.Config.ThumbnailSize));
|
||||
ilThumbnailList.Images.Add(thumbnails[img]);
|
||||
Items.Add("", ilThumbnailList.Images.Count - 1);
|
||||
}
|
||||
|
||||
public void ClearItems()
|
||||
public void ReplaceThumbnail(int index, ScannedImage img)
|
||||
{
|
||||
ClearImages();
|
||||
Clear();
|
||||
}
|
||||
|
||||
private void ClearImages()
|
||||
{
|
||||
foreach (Image img in ilThumbnailList.Images)
|
||||
{
|
||||
img.Dispose();
|
||||
}
|
||||
ilThumbnailList.Images.Clear();
|
||||
}
|
||||
|
||||
public void ReplaceThumbnail(int index, Bitmap thumbnail)
|
||||
{
|
||||
ilThumbnailList.Images[index].Dispose();
|
||||
ilThumbnailList.Images[index] = thumbnail;
|
||||
ilThumbnailList.Images[index] = thumbnails[img];
|
||||
Invalidate(Items[index].Bounds);
|
||||
}
|
||||
|
||||
public void RegenerateThumbnailList(List<ScannedImage> images)
|
||||
{
|
||||
var thumbnails = images.Select(x => (Image)x.GetThumbnail(UserConfigManager.Config.ThumbnailSize)).ToArray();
|
||||
ilThumbnailList.Images.AddRange(thumbnails);
|
||||
var thumbnailArray = images.Select(x => (Image)thumbnails[x]).ToArray();
|
||||
ilThumbnailList.Images.AddRange(thumbnailArray);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user