mirror of
https://github.com/MaaAssistantArknights/MaaAssistantArknights.git
synced 2026-07-15 17:30:27 +08:00
perf: 优化物品图显示缓存
This commit is contained in:
@@ -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;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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"
|
||||
|
||||
Reference in New Issue
Block a user