You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
705 lines
24 KiB
705 lines
24 KiB
using System;
|
|
using System.Collections.Concurrent;
|
|
using System.Collections.Generic;
|
|
using System.Net.Http;
|
|
using System.Runtime.CompilerServices;
|
|
using System.Runtime.InteropServices;
|
|
using System.Text.RegularExpressions;
|
|
using System.Threading;
|
|
using System.Threading.Tasks;
|
|
using System.Threading.Tasks.Schedulers;
|
|
using System.Windows;
|
|
using System.Windows.Controls;
|
|
using System.Windows.Interop;
|
|
using System.Windows.Media;
|
|
using System.Windows.Media.Imaging;
|
|
using System.Windows.Resources;
|
|
using dw = System.Drawing;
|
|
|
|
namespace SJ.Controls
|
|
{
|
|
public class BAsyncImage : Control
|
|
{
|
|
#region DependencyProperty
|
|
public static readonly DependencyProperty DecodePixelWidthProperty = DependencyProperty.Register("DecodePixelWidth",
|
|
typeof(double), typeof(BAsyncImage), new PropertyMetadata(0.0));
|
|
|
|
public static readonly DependencyProperty LoadingTextProperty =
|
|
DependencyProperty.Register("LoadingText", typeof(string), typeof(BAsyncImage), new PropertyMetadata("Loading..."));
|
|
|
|
public static readonly DependencyProperty IsLoadingProperty =
|
|
DependencyProperty.Register("IsLoading", typeof(bool), typeof(BAsyncImage), new PropertyMetadata(false));
|
|
|
|
public static readonly DependencyProperty ImageSourceProperty = DependencyProperty.Register("ImageSource", typeof(ImageSource), typeof(BAsyncImage));
|
|
|
|
public static readonly DependencyProperty DefaultUrlSourceProperty = DependencyProperty.Register("DefaultUrlSource", typeof(string), typeof(BAsyncImage), new PropertyMetadata(""));
|
|
|
|
public static readonly DependencyProperty UrlSourceProperty =
|
|
DependencyProperty.Register("UrlSource", typeof(string), typeof(BAsyncImage), new PropertyMetadata(string.Empty, new PropertyChangedCallback((s, e) =>
|
|
{
|
|
var asyncImg = s as BAsyncImage;
|
|
if (asyncImg.LoadEventFlag)
|
|
{
|
|
asyncImg.Load();
|
|
}
|
|
})));
|
|
|
|
public static readonly DependencyProperty FailUrlSourceProperty =
|
|
DependencyProperty.Register("FailUrlSource", typeof(string), typeof(BAsyncImage), new PropertyMetadata(string.Empty));
|
|
|
|
public static readonly DependencyProperty IsCacheProperty = DependencyProperty.Register("IsCache", typeof(bool), typeof(BAsyncImage), new PropertyMetadata(true));
|
|
|
|
public static readonly DependencyProperty StretchProperty = DependencyProperty.Register("Stretch", typeof(Stretch), typeof(BAsyncImage), new PropertyMetadata(Stretch.Uniform));
|
|
|
|
public static readonly DependencyProperty CacheGroupProperty = DependencyProperty.Register("CacheGroup", typeof(string), typeof(BAsyncImage), new PropertyMetadata("QLAsyncImage_Default"));
|
|
#endregion
|
|
|
|
#region Property
|
|
private static readonly HttpClient httpClient = new HttpClient();
|
|
|
|
public double StaticImageActualPixelWidth { get; set; } = 0;
|
|
|
|
public double StaticImageActualPixelHeight { get; set; } = 0;
|
|
|
|
public const string LocalRegex = @"^([C-J]):\\([^:&]+\\)*([^:&]+).(jpg|jpeg|png|gif)$";
|
|
public const string HttpRegex = @"^((https|http):\/\/)?([^\\*+@]+)$";
|
|
|
|
private Image _image;
|
|
private dw.Bitmap gifBitmap;
|
|
private bool LoadEventFlag = false;
|
|
private static ConcurrentDictionary<string, ImageSource> ImageCacheList;
|
|
private static ConcurrentDictionary<string, byte[]> GifImageCacheList;
|
|
|
|
private static LimitedConcurrencyLevelTaskScheduler httpTaskScheduler;
|
|
|
|
public double DecodePixelWidth
|
|
{
|
|
get { return (double)GetValue(DecodePixelWidthProperty); }
|
|
set { SetValue(DecodePixelWidthProperty, value); }
|
|
}
|
|
public string LoadingText
|
|
{
|
|
get { return GetValue(LoadingTextProperty) as string; }
|
|
set { SetValue(LoadingTextProperty, value); }
|
|
}
|
|
|
|
public bool IsLoading
|
|
{
|
|
get { return (bool)GetValue(IsLoadingProperty); }
|
|
set { SetValue(IsLoadingProperty, value); }
|
|
}
|
|
|
|
public string UrlSource
|
|
{
|
|
get { return GetValue(UrlSourceProperty) as string; }
|
|
set { SetValue(UrlSourceProperty, value); }
|
|
}
|
|
|
|
/// <summary>
|
|
/// 仅限Resourcesl路径
|
|
/// </summary>
|
|
public string FailUrlSource
|
|
{
|
|
get { return GetValue(FailUrlSourceProperty) as string; }
|
|
set { SetValue(FailUrlSourceProperty, value); }
|
|
}
|
|
|
|
public ImageSource ImageSource
|
|
{
|
|
get { return GetValue(ImageSourceProperty) as ImageSource; }
|
|
set { SetValue(ImageSourceProperty, value); }
|
|
}
|
|
|
|
public bool IsCache
|
|
{
|
|
get { return (bool)GetValue(IsCacheProperty); }
|
|
set { SetValue(IsCacheProperty, value); }
|
|
}
|
|
|
|
public Stretch Stretch
|
|
{
|
|
get { return (Stretch)GetValue(StretchProperty); }
|
|
set { SetValue(StretchProperty, value); }
|
|
}
|
|
|
|
public string CacheGroup
|
|
{
|
|
get { return GetValue(CacheGroupProperty) as string; }
|
|
set { SetValue(CacheGroupProperty, value); }
|
|
}
|
|
|
|
#endregion
|
|
|
|
#region RouteEvent
|
|
public delegate void QLAsyncImageLoadCompleteHandler(object sender, QLAsyncImageLoadCompleteEventArgs e);
|
|
|
|
public static readonly RoutedEvent OnLoadCompleteEvent = EventManager.RegisterRoutedEvent("OnLoadComplete", RoutingStrategy.Bubble, typeof(QLAsyncImageLoadCompleteHandler), typeof(BAsyncImage));
|
|
|
|
public event QLAsyncImageLoadCompleteHandler OnLoadComplete
|
|
{
|
|
add { AddHandler(OnLoadCompleteEvent, value); }
|
|
remove { RemoveHandler(OnLoadCompleteEvent, value); }
|
|
}
|
|
#endregion
|
|
|
|
#region Method
|
|
static BAsyncImage()
|
|
{
|
|
DefaultStyleKeyProperty.OverrideMetadata(typeof(BAsyncImage), new FrameworkPropertyMetadata(typeof(BAsyncImage)));
|
|
ImageCacheList = new ConcurrentDictionary<string, ImageSource>();
|
|
GifImageCacheList = new ConcurrentDictionary<string, byte[]>();
|
|
httpTaskScheduler = new LimitedConcurrencyLevelTaskScheduler(10);
|
|
}
|
|
|
|
public BAsyncImage()
|
|
{
|
|
Loaded += QLAsyncImage_Loaded;
|
|
Unloaded += QLAsyncImage_Unloaded;
|
|
}
|
|
|
|
private void QLAsyncImage_Unloaded(object sender, RoutedEventArgs e)
|
|
{
|
|
Reset();
|
|
LoadEventFlag = false;
|
|
}
|
|
|
|
private void QLAsyncImage_Loaded(object sender, RoutedEventArgs e)
|
|
{
|
|
Init();
|
|
}
|
|
|
|
public override void OnApplyTemplate()
|
|
{
|
|
Init();
|
|
}
|
|
|
|
private void Init([CallerMemberName] string eventName = "")
|
|
{
|
|
if (LoadEventFlag)
|
|
return;
|
|
|
|
_image = GetTemplateChild("image") as Image;
|
|
|
|
if (_image == null)
|
|
return;
|
|
|
|
LoadEventFlag = true;
|
|
Load();
|
|
}
|
|
|
|
/// <summary>
|
|
/// Delete local bitmap resource
|
|
/// Reference: http://msdn.microsoft.com/en-us/library/dd183539(VS.85).aspx
|
|
/// </summary>
|
|
[DllImport("gdi32.dll", CharSet = CharSet.Auto, SetLastError = true)]
|
|
[return: MarshalAs(UnmanagedType.Bool)]
|
|
static extern bool DeleteObject(IntPtr hObject);
|
|
|
|
/// <summary>
|
|
/// 重置图像
|
|
/// </summary>
|
|
private void Reset()
|
|
{
|
|
//停止播放Gif动画
|
|
if (gifBitmap != null)
|
|
StopGif();
|
|
SetSource(null);
|
|
}
|
|
|
|
private void Load()
|
|
{
|
|
if (_image == null)
|
|
return;
|
|
|
|
Reset();
|
|
|
|
if (!string.IsNullOrEmpty(UrlSource))
|
|
{
|
|
var url = UrlSource;
|
|
var failUrl = FailUrlSource;
|
|
var pixelWidth = (int)DecodePixelWidth;
|
|
var isCache = IsCache;
|
|
var cacheKey = string.Format("{0}_{1}", CacheGroup, url);
|
|
IsLoading = !ImageCacheList.ContainsKey(cacheKey) && !GifImageCacheList.ContainsKey(cacheKey);
|
|
|
|
#region 读取缓存
|
|
if (ImageCacheList.ContainsKey(cacheKey))
|
|
{
|
|
var source = ImageCacheList[cacheKey];
|
|
SetSource(source);
|
|
SetStaticImageActualPixelSize(source.Width, source.Height);
|
|
LoadComplete(string.Empty, url);
|
|
return;
|
|
}
|
|
else if (GifImageCacheList.ContainsKey(cacheKey))
|
|
{
|
|
PlayGif(GifImageCacheList[cacheKey]);
|
|
LoadComplete(string.Empty, url);
|
|
return;
|
|
}
|
|
#endregion
|
|
|
|
this.Load(url, failUrl, cacheKey, isCache, pixelWidth);
|
|
}
|
|
}
|
|
|
|
private void Load(string url, string failUrl, string cacheKey, bool isCache, int pixelWidth)
|
|
{
|
|
var errorMessage = string.Empty;
|
|
|
|
//解析路径类型
|
|
var pathType = ValidatePathType(url);
|
|
if (pathType == PathType.Invalid)
|
|
{
|
|
LoadFail(failUrl);
|
|
LoadComplete(errorMessage, url);
|
|
return;
|
|
}
|
|
|
|
if (pathType == PathType.Http)
|
|
{
|
|
////先加载默认图
|
|
//if (!string.IsNullOrEmpty(defaultUrl))
|
|
// LoadLocal(defaultUrl, failUrl, PathType.Resources, defaultUrl, true, 0, excuteComplete: false); //默认图不触发加载完毕事件
|
|
LoadHttp(url, failUrl, cacheKey, isCache, pixelWidth);
|
|
}
|
|
else
|
|
LoadLocal(url, failUrl, pathType, cacheKey, isCache, pixelWidth);
|
|
}
|
|
|
|
/// <summary>
|
|
/// 加载失败图像
|
|
/// </summary>
|
|
/// <param name="failUrl"></param>
|
|
private void LoadFail(string failUrl)
|
|
{
|
|
byte[] imgBytes = null;
|
|
string errorMessage = string.Empty;
|
|
var pathType = ValidatePathType(failUrl);
|
|
if (pathType == PathType.Invalid)
|
|
{
|
|
Console.ForegroundColor = ConsoleColor.Red;
|
|
Console.WriteLine($"LoadFail 无效的路径 {failUrl}");
|
|
Console.ResetColor();
|
|
return;
|
|
}
|
|
if (pathType == PathType.Local)
|
|
imgBytes = LoadBytesFromLocal(failUrl, out errorMessage);
|
|
else if (pathType == PathType.Resources)
|
|
imgBytes = LoadBytesFromApplicationResource(failUrl, out errorMessage);
|
|
|
|
|
|
if (string.IsNullOrEmpty(errorMessage) && imgBytes != null)
|
|
AnalysisBytes(imgBytes, failUrl, true, 0, out errorMessage);
|
|
|
|
if (string.IsNullOrEmpty(errorMessage))
|
|
return;
|
|
|
|
Console.ForegroundColor = ConsoleColor.Red;
|
|
Console.WriteLine($"LoadFail {errorMessage} {failUrl}");
|
|
Console.ResetColor();
|
|
}
|
|
|
|
private void LoadLocal(string url, string failUrl, PathType pathType, string cacheKey, bool isCache, int pixelWidth, bool excuteComplete = true)
|
|
{
|
|
byte[] imgBytes = null;
|
|
var errorMessage = string.Empty;
|
|
if (pathType == PathType.Local)
|
|
imgBytes = LoadBytesFromLocal(url, out errorMessage);
|
|
else if (pathType == PathType.Resources)
|
|
imgBytes = LoadBytesFromApplicationResource(url, out errorMessage);
|
|
|
|
if (string.IsNullOrEmpty(errorMessage) && imgBytes != null)
|
|
AnalysisBytes(imgBytes, cacheKey, isCache, pixelWidth, out errorMessage);
|
|
|
|
if (!string.IsNullOrEmpty(errorMessage))
|
|
{
|
|
LoadFail(failUrl);
|
|
Console.ForegroundColor = ConsoleColor.Red;
|
|
}
|
|
Console.WriteLine($"LoadLocal {errorMessage} {url}");
|
|
Console.ResetColor();
|
|
if (excuteComplete)
|
|
LoadComplete(errorMessage, url);
|
|
return;
|
|
}
|
|
|
|
private void LoadHttp(string url, string failUrl, string cacheKey, bool isCache, int pixelWidth)
|
|
{
|
|
Task.Factory.StartNew(() =>
|
|
{
|
|
//Thread.Sleep(2000);
|
|
Console.WriteLine($"LoadHttp Start {url}");
|
|
var errorMessage = string.Empty;
|
|
var imgBytes = LoadBytesFromHttp(url, out errorMessage);
|
|
|
|
if (string.IsNullOrEmpty(errorMessage) && imgBytes != null)
|
|
AnalysisBytes(imgBytes, cacheKey, isCache, pixelWidth, out errorMessage);
|
|
|
|
if (!string.IsNullOrEmpty(errorMessage))
|
|
{
|
|
LoadFail(failUrl);
|
|
Console.ForegroundColor = ConsoleColor.Red;
|
|
}
|
|
Console.WriteLine($"LoadHttp Completed {errorMessage} {url}");
|
|
Console.ResetColor();
|
|
LoadComplete(errorMessage, url);
|
|
return;
|
|
}, CancellationToken.None, TaskCreationOptions.None, httpTaskScheduler);
|
|
}
|
|
|
|
private void AnalysisBytes(byte[] imgBytes, string cacheKey, bool isCache, int pixelWidth, out string errorMessage)
|
|
{
|
|
errorMessage = string.Empty;
|
|
|
|
#region 读取文件类型
|
|
var imgType = GetImageType(imgBytes);
|
|
if (imgType == ImageType.Invalid)
|
|
{
|
|
imgBytes = null;
|
|
errorMessage = "Invalid ImageFile";
|
|
return;
|
|
}
|
|
#endregion
|
|
|
|
#region 加载图像
|
|
if (imgType != ImageType.Gif)
|
|
{
|
|
//加载静态图像
|
|
var imgSource = LoadStaticImage(cacheKey, imgBytes, pixelWidth, isCache, out errorMessage);
|
|
if (imgSource == null)
|
|
return;
|
|
SetStaticImageActualPixelSize(imgSource.Width, imgSource.Height);
|
|
SetSource(imgSource);
|
|
}
|
|
else
|
|
{
|
|
var frameCount = 0;
|
|
using (var memoryStream = new System.IO.MemoryStream(imgBytes))
|
|
{
|
|
//读取gif帧数
|
|
var decoder = BitmapDecoder.Create(memoryStream, BitmapCreateOptions.PreservePixelFormat, BitmapCacheOption.OnLoad);
|
|
frameCount = decoder.Frames.Count;
|
|
decoder = null;
|
|
}
|
|
if (frameCount > 1)
|
|
{
|
|
CacheGifBytes(cacheKey, imgBytes, isCache);
|
|
PlayGif(imgBytes);
|
|
}
|
|
else
|
|
{
|
|
//gif只有1帧,视为静态图处理
|
|
var imgSource = LoadStaticImage(cacheKey, imgBytes, pixelWidth, isCache, out errorMessage);
|
|
if (imgSource == null)
|
|
return;
|
|
SetStaticImageActualPixelSize(imgSource.Width, imgSource.Height);
|
|
SetSource(imgSource);
|
|
}
|
|
}
|
|
#endregion
|
|
}
|
|
|
|
|
|
/// <summary>
|
|
/// 加载静态图像
|
|
/// </summary>
|
|
/// <param name="cacheKey"></param>
|
|
/// <param name="imgBytes"></param>
|
|
/// <param name="pixelWidth"></param>
|
|
/// <param name="isCache"></param>
|
|
/// <returns></returns>
|
|
private ImageSource LoadStaticImage(string cacheKey, byte[] imgBytes, int pixelWidth, bool isCache, out string errorMessage)
|
|
{
|
|
errorMessage = string.Empty;
|
|
if (ImageCacheList.ContainsKey(cacheKey))
|
|
return ImageCacheList[cacheKey];
|
|
var bit = new BitmapImage() { CacheOption = BitmapCacheOption.OnLoad };
|
|
try
|
|
{
|
|
bit.BeginInit();
|
|
if (pixelWidth != 0)
|
|
{
|
|
bit.DecodePixelWidth = pixelWidth;
|
|
}
|
|
bit.StreamSource = new System.IO.MemoryStream(imgBytes);
|
|
bit.EndInit();
|
|
bit.Freeze();
|
|
if (isCache && !ImageCacheList.ContainsKey(cacheKey))
|
|
ImageCacheList.TryAdd(cacheKey, bit);
|
|
}
|
|
catch (Exception ex)
|
|
{
|
|
errorMessage = $"LoadStaticImage Error {ex.Message}";
|
|
bit = null;
|
|
}
|
|
return bit;
|
|
}
|
|
|
|
/// <summary>
|
|
/// 加载Gif图像动画
|
|
/// </summary>
|
|
/// <param name="cacheKey"></param>
|
|
/// <param name="imgBytes"></param>
|
|
/// <param name="pixelWidth"></param>
|
|
/// <param name="isCache"></param>
|
|
/// <returns></returns>
|
|
private void CacheGifBytes(string cacheKey, byte[] imgBytes, bool isCache)
|
|
{
|
|
if (isCache && !GifImageCacheList.ContainsKey(cacheKey))
|
|
GifImageCacheList.TryAdd(cacheKey, imgBytes);
|
|
}
|
|
|
|
private byte[] LoadBytesFromHttp(string url, out string errorMessage)
|
|
{
|
|
errorMessage = string.Empty;
|
|
try
|
|
{
|
|
return httpClient.GetByteArrayAsync(url).Result;
|
|
}
|
|
catch (Exception ex)
|
|
{
|
|
errorMessage = $"Dowdload Error {ex.Message}";
|
|
}
|
|
return null;
|
|
}
|
|
|
|
private byte[] LoadBytesFromLocal(string path, out string errorMessage)
|
|
{
|
|
errorMessage = string.Empty;
|
|
if (!System.IO.File.Exists(path))
|
|
{
|
|
errorMessage = "File No Exists";
|
|
return null;
|
|
}
|
|
try
|
|
{
|
|
return System.IO.File.ReadAllBytes(path);
|
|
}
|
|
catch (Exception ex)
|
|
{
|
|
errorMessage = $"Load Local Error {ex.Message}";
|
|
return null;
|
|
}
|
|
}
|
|
|
|
private byte[] LoadBytesFromApplicationResource(string path, out string errorMessage)
|
|
{
|
|
errorMessage = string.Empty;
|
|
try
|
|
{
|
|
StreamResourceInfo streamInfo = Application.GetResourceStream(new Uri(path, UriKind.RelativeOrAbsolute));
|
|
if (streamInfo.Stream.CanRead)
|
|
{
|
|
using (streamInfo.Stream)
|
|
{
|
|
var bytes = new byte[streamInfo.Stream.Length];
|
|
streamInfo.Stream.Read(bytes, 0, bytes.Length);
|
|
return bytes;
|
|
}
|
|
}
|
|
}
|
|
catch (Exception ex)
|
|
{
|
|
errorMessage = $"Load Resource Error {ex.Message}";
|
|
return null;
|
|
}
|
|
return null;
|
|
}
|
|
|
|
private void SetSource(ImageSource source)
|
|
{
|
|
Dispatcher.BeginInvoke((Action)delegate
|
|
{
|
|
if (_image != null)
|
|
_image.Source = source;
|
|
});
|
|
}
|
|
|
|
/// <summary>
|
|
/// 更新图像实际像素
|
|
/// </summary>
|
|
/// <param name="pixelWidth"></param>
|
|
private void SetStaticImageActualPixelSize(double pixelWidth, double pixelHeight)
|
|
{
|
|
Dispatcher.Invoke(() =>
|
|
{
|
|
StaticImageActualPixelWidth = pixelWidth;
|
|
StaticImageActualPixelHeight = pixelHeight;
|
|
});
|
|
}
|
|
|
|
private void PlayGif(byte[] imgBytes)
|
|
{
|
|
gifBitmap = new dw.Bitmap(new System.IO.MemoryStream(imgBytes));
|
|
if (dw.ImageAnimator.CanAnimate(gifBitmap))
|
|
{
|
|
SetStaticImageActualPixelSize(gifBitmap.Width, gifBitmap.Height);
|
|
dw.ImageAnimator.Animate(gifBitmap, OnGifFrameChanged);
|
|
}
|
|
else
|
|
{
|
|
gifBitmap.Dispose();
|
|
}
|
|
}
|
|
|
|
private void StopGif()
|
|
{
|
|
dw.ImageAnimator.StopAnimate(gifBitmap, OnGifFrameChanged);
|
|
gifBitmap.Dispose();
|
|
}
|
|
|
|
private void OnGifFrameChanged(object sender, EventArgs e)
|
|
{
|
|
dw.ImageAnimator.UpdateFrames();
|
|
var currentFrameImageSource = GetBitmapSource();
|
|
if (currentFrameImageSource != null)
|
|
currentFrameImageSource.Freeze();
|
|
SetSource(currentFrameImageSource);
|
|
}
|
|
|
|
/// <summary>
|
|
/// 加载完成
|
|
/// </summary>
|
|
/// <param name="errorMessage"></param>
|
|
/// <param name="url"></param>
|
|
private void LoadComplete(string errorMessage, string url)
|
|
{
|
|
this.Dispatcher.BeginInvoke((Action)delegate
|
|
{
|
|
IsLoading = false;
|
|
var args = new QLAsyncImageLoadCompleteEventArgs(OnLoadCompleteEvent, this)
|
|
{
|
|
IsSuccess = string.IsNullOrEmpty(errorMessage),
|
|
UrlSource = url,
|
|
ErrorMessage = errorMessage,
|
|
StaticImageActualPixelWidth = StaticImageActualPixelWidth,
|
|
StaticImageActualPixelHeight = StaticImageActualPixelHeight
|
|
};
|
|
this.RaiseEvent(args);
|
|
});
|
|
}
|
|
|
|
/// <summary>
|
|
/// 从System.Drawing.Bitmap中获得当前帧图像的BitmapSource
|
|
/// </summary>
|
|
/// <returns></returns>
|
|
private ImageSource GetBitmapSource()
|
|
{
|
|
IntPtr handle = IntPtr.Zero;
|
|
try
|
|
{
|
|
handle = gifBitmap.GetHbitmap();
|
|
return Imaging.CreateBitmapSourceFromHBitmap(handle, IntPtr.Zero, System.Windows.Int32Rect.Empty, BitmapSizeOptions.FromEmptyOptions());
|
|
}
|
|
catch
|
|
{
|
|
return null;
|
|
}
|
|
finally
|
|
{
|
|
if (handle != IntPtr.Zero)
|
|
{
|
|
DeleteObject(handle);
|
|
}
|
|
}
|
|
}
|
|
|
|
public void Refresh()
|
|
{
|
|
Load();
|
|
}
|
|
|
|
private PathType ValidatePathType(string path)
|
|
{
|
|
if (path.StartsWith("pack://"))
|
|
return PathType.Resources;
|
|
else if (Regex.IsMatch(path, BAsyncImage.LocalRegex, RegexOptions.IgnoreCase))
|
|
return PathType.Local;
|
|
else if (Regex.IsMatch(path, BAsyncImage.HttpRegex, RegexOptions.IgnoreCase))
|
|
return PathType.Http;
|
|
else
|
|
return PathType.Invalid;
|
|
}
|
|
|
|
private ImageType GetImageType(byte[] bytes)
|
|
{
|
|
var type = ImageType.Invalid;
|
|
try
|
|
{
|
|
var fileHead = Convert.ToInt32($"{bytes[0]}{bytes[1]}");
|
|
if (!Enum.IsDefined(typeof(ImageType), fileHead))
|
|
{
|
|
type = ImageType.Invalid;
|
|
}
|
|
else
|
|
{
|
|
type = (ImageType)fileHead;
|
|
}
|
|
}
|
|
catch (Exception ex)
|
|
{
|
|
type = ImageType.Invalid;
|
|
Console.WriteLine($"获取图片类型失败 {ex.Message}");
|
|
}
|
|
return type;
|
|
}
|
|
|
|
/// <summary>
|
|
/// 清楚缓存
|
|
/// </summary>
|
|
/// <param name="cacheKey">缓存Key,格式: CacheGroup_UrlSource</param>
|
|
public static void ClearCache(string cacheKey = "")
|
|
{
|
|
if (string.IsNullOrEmpty(cacheKey))
|
|
{
|
|
ImageCacheList.Clear();
|
|
GifImageCacheList.Clear();
|
|
return;
|
|
}
|
|
|
|
ImageCacheList.Remove(cacheKey, out _);
|
|
GifImageCacheList.Remove(cacheKey, out _);
|
|
}
|
|
|
|
public static ImageSource GetImageCache(string cacheKey)
|
|
{
|
|
if (ImageCacheList.ContainsKey(cacheKey))
|
|
return ImageCacheList[cacheKey];
|
|
return null;
|
|
}
|
|
#endregion
|
|
}
|
|
|
|
|
|
public enum PathType
|
|
{
|
|
Invalid = 0, Local = 1, Http = 2, Resources = 3
|
|
}
|
|
|
|
public enum ImageType
|
|
{
|
|
Invalid = 0, Gif = 7173, Jpg = 255216, Png = 13780, Bmp = 6677
|
|
}
|
|
|
|
public class QLAsyncImageLoadCompleteEventArgs : RoutedEventArgs
|
|
{
|
|
public QLAsyncImageLoadCompleteEventArgs(RoutedEvent routedEvent, object source) : base(routedEvent, source) { }
|
|
|
|
public bool IsSuccess { get; set; }
|
|
|
|
public string UrlSource { get; set; }
|
|
|
|
public string ErrorMessage { get; set; }
|
|
|
|
/// <summary>
|
|
/// 当加载静态图时的实际像素宽度
|
|
/// </summary>
|
|
public double StaticImageActualPixelWidth { get; set; }
|
|
|
|
/// <summary>
|
|
/// 当加载静态图时的实际像素高度
|
|
/// </summary>
|
|
public double StaticImageActualPixelHeight { get; set; }
|
|
}
|
|
}
|
|
|