perf: 优化物品图显示缓存

This commit is contained in:
uye
2025-07-11 20:38:12 +08:00
committed by MistEO
parent b0462076ea
commit e38e8cf01a
2 changed files with 58 additions and 44 deletions

View File

@@ -14,6 +14,7 @@
#nullable enable
using System;
using System.Collections.Concurrent;
using System.Collections.Generic;
using System.IO;
using System.Text.Json;
@@ -84,56 +85,80 @@ namespace MaaWpfGui.Helper
: itemId;
}
private static readonly ConcurrentDictionary<string, BitmapSource?> _imageCache = new();
/// <summary>
/// 获取对应物品的图标 / Get the icon of the corresponding item
/// </summary>
/// <param name="itemId">物品 id / Item id</param>
/// <returns>物品图片</returns>
public static BitmapImage? GetItemImage(string itemId)
public static BitmapSource? GetItemImage(string itemId)
{
if (_imageCache.TryGetValue(itemId, out var cachedImage))
{
return cachedImage;
}
var imagePath = Path.Combine(Environment.CurrentDirectory, $"resource/template/items/{itemId}.png");
if (!File.Exists(imagePath))
{
_imageCache.TryAdd(itemId, null);
return null;
}
try
{
var bitmapImage = new BitmapImage(new(imagePath, UriKind.RelativeOrAbsolute));
var stride = bitmapImage.PixelWidth * ((bitmapImage.Format.BitsPerPixel + 7) / 8);
var pixelData = new byte[stride * bitmapImage.PixelHeight];
bitmapImage.CopyPixels(pixelData, stride, 0);
// 把黑边变成透明其实是所有的黑色都变成透明了x
for (int i = 0; i < pixelData.Length; i += 4)
{
if (pixelData[i] == 0 && pixelData[i + 1] == 0 && pixelData[i + 2] == 0)
{
pixelData[i + 3] = 0;
}
}
// 不知道为啥 WriteableBitmap(bitmapImage); 得到的图没有透明度,大概是原始 uri 对应的是个 24 位的图?手动处理一下
var writeableBitmap = new WriteableBitmap(bitmapImage.PixelWidth, bitmapImage.PixelHeight, bitmapImage.DpiX, bitmapImage.DpiY, PixelFormats.Bgra32, null);
writeableBitmap.WritePixels(new(0, 0, bitmapImage.PixelWidth, bitmapImage.PixelHeight), pixelData, stride, 0);
bitmapImage = new();
using MemoryStream stream = new MemoryStream();
PngBitmapEncoder encoder = new PngBitmapEncoder();
encoder.Frames.Add(BitmapFrame.Create(writeableBitmap));
encoder.Save(stream);
bitmapImage.BeginInit();
bitmapImage.CacheOption = BitmapCacheOption.OnLoad;
bitmapImage.StreamSource = stream;
bitmapImage.EndInit();
bitmapImage.Freeze();
return bitmapImage;
var processedImage = ProcessBlackToTransparent(imagePath);
_imageCache.TryAdd(itemId, processedImage);
return processedImage;
}
catch
{
_imageCache.TryAdd(itemId, null);
return null;
}
}
private static BitmapSource ProcessBlackToTransparent(string imagePath)
{
var original = new BitmapImage();
original.BeginInit();
original.CacheOption = BitmapCacheOption.OnLoad;
original.UriSource = new(imagePath, UriKind.RelativeOrAbsolute);
original.EndInit();
var convertedBitmap = new FormatConvertedBitmap(original, PixelFormats.Bgra32, null, 0);
var writeable = new WriteableBitmap(convertedBitmap);
writeable.Lock();
try
{
unsafe
{
var pixels = (uint*)writeable.BackBuffer;
int pixelCount = writeable.PixelWidth * writeable.PixelHeight;
for (int i = 0; i < pixelCount; i++)
{
uint pixel = pixels[i];
uint bgr = pixel & 0x00FFFFFF;
if (bgr == 0)
{
pixels[i] = 0x00000000;
}
}
}
writeable.AddDirtyRect(new(0, 0, writeable.PixelWidth, writeable.PixelHeight));
}
finally
{
writeable.Unlock();
}
writeable.Freeze();
return writeable;
}
}
}

View File

@@ -354,7 +354,7 @@ namespace MaaWpfGui.ViewModels.UI
public string Id { get; set; } = null!;
public BitmapImage? Image { get; set; }
public BitmapSource? Image { get; set; }
public string? Count { get; set; }
}
@@ -398,11 +398,6 @@ namespace MaaWpfGui.ViewModels.UI
/// </summary>
public string LoliconResult { get; set; } = string.Empty;
/// <summary>
/// gets or sets the depot image.
/// </summary>
private static readonly Dictionary<string, BitmapImage?> _imageCache = new();
/// <summary>
/// parse of depot recognition result
/// </summary>
@@ -430,17 +425,11 @@ namespace MaaWpfGui.ViewModels.UI
continue;
}
if (!_imageCache.TryGetValue(id, out var image))
{
image = ItemListHelper.GetItemImage(id);
_imageCache[id] = image;
}
DepotResultDate result = new()
{
Id = id,
Name = ItemListHelper.GetItemName(id),
Image = image,
Image = ItemListHelper.GetItemImage(id),
Count = item["have"] != null && int.TryParse(item["have"]?.ToString() ?? "-1", out int haveValue)
? (haveValue > 10000
? $"{haveValue / 10000.0:F1}w"