* UIGifAvatar: 重写图片刷新流程,减少内存及GC

This commit is contained in:
Sunny 2022-07-25 17:57:52 +08:00
parent 88d551b5e3
commit c0ccb4cfd0

View File

@ -17,6 +17,7 @@
* : 2022-07-01
*
* 2022-07-01: V3.2.0
* 2022-07-25: V3.2.2 GC
******************************************************************************/
using System;
@ -47,6 +48,7 @@ namespace Sunny.UI
~UIGifAvatar()
{
Active = false;
Clear();
}
/// <summary>
@ -124,7 +126,7 @@ namespace Sunny.UI
}
}
ShowImage();
CalcImages();
Invalidate();
}
@ -132,6 +134,37 @@ namespace Sunny.UI
}
}
private void Clear()
{
foreach (var item in Images.Values)
{
item.Dispose();
}
}
private void CalcImages()
{
FrameIndex = -1;
Clear();
if (Image == null) return;
Images.Clear();
if (!IsGif)
{
Images.TryAdd(0, ScaleImage(0));
}
else
{
for (int i = 0; i < ImageCount; i++)
{
Images.TryAdd(i, ScaleImage(i));
}
}
FrameIndex = 0;
}
private ConcurrentDictionary<int, Image> Images = new ConcurrentDictionary<int, Image>();
private int avatarSize = 120;
@ -143,12 +176,11 @@ namespace Sunny.UI
set
{
avatarSize = value;
ShowImage();
CalcImages();
Invalidate();
}
}
private int ImageCount;
public bool IsGif => ImageCount > 0;
@ -178,97 +210,67 @@ namespace Sunny.UI
protected override void OnSizeChanged(EventArgs e)
{
base.OnSizeChanged(e);
ShowImage();
CalcImages();
Invalidate();
}
private Image RoundImage;
public void ShowImage()
{
int size = avatarSize;
if (Image == null)
{
return;
}
if (RoundImage != null)
{
if (RoundImage.Width != Width || RoundImage.Height != Height)
{
RoundImage.Dispose();
RoundImage = null;
}
}
if (RoundImage == null)
{
RoundImage = new Bitmap(Width, Height);
}
Graphics g = Graphics.FromImage(RoundImage);
g.Clear(FillColor);
float sc1 = Image.Width * 1.0f / size;
float sc2 = Image.Height * 1.0f / size;
int drawSize = Math.Min(Width, Height);
Image bmp = ScaleImage(Math.Min(sc1, sc2));
if (bmp != null)
{
g.DrawImage(bmp, (drawSize - avatarSize) / 2, (drawSize - avatarSize) / 2);
bmp.Dispose();
}
g.DrawEllipse(rectColor, new Rectangle((drawSize - AvatarSize) / 2, (drawSize - AvatarSize) / 2,
AvatarSize, AvatarSize), true, RectSize);
}
public bool ShowScore { get; set; } = true;
private Image ScaleImage(float size)
private Image ScaleImage(int frameIndex)
{
if (Image == null)
{
return null;
}
var img = new Bitmap(Width, Height);
Graphics g = img.Graphics();
g.Clear(FillColor);
float size = avatarSize;
float sc1 = Image.Width * 1.0f / size;
float sc2 = Image.Height * 1.0f / size;
size = Math.Min(sc1, sc2);
Bitmap scaleImage;
Bitmap result;
if (!IsGif)
{
Bitmap scaleImage = ((Bitmap)Image).ResizeImage((int)(Image.Width * 1.0 / size + 0.5),
(int)(Image.Height * 1.0 / size + 0.5));
Bitmap result = scaleImage.Split(avatarSize, UIShape.Circle);
scaleImage.Dispose();
return result;
scaleImage = ((Bitmap)Image).ResizeImage((int)(Image.Width * 1.0 / size + 0.5), (int)(Image.Height * 1.0 / size + 0.5));
result = scaleImage.Split(avatarSize, UIShape.Circle);
}
else
{
FrameDimension fd = new FrameDimension(Image.FrameDimensionsList[0]);
Image.SelectActiveFrame(fd, FrameIndex);
Image.SelectActiveFrame(fd, frameIndex);
Bitmap imageEx = new Bitmap(Image.Width, Image.Height);
Graphics g = Graphics.FromImage(imageEx);
g.DrawImage(Image, new Point(0, 0));
Bitmap scaleImage = imageEx.ResizeImage((int)(Image.Width * 1.0 / size + 0.5), (int)(Image.Height * 1.0 / size + 0.5));
Bitmap result = scaleImage.Split(avatarSize, UIShape.Circle);
scaleImage.Dispose();
Graphics gx = Graphics.FromImage(imageEx);
gx.DrawImage(Image, new Point(0, 0));
scaleImage = imageEx.ResizeImage((int)(Image.Width * 1.0 / size + 0.5), (int)(Image.Height * 1.0 / size + 0.5));
result = scaleImage.Split(avatarSize, UIShape.Circle);
imageEx.Dispose();
return result;
}
int drawSize = Math.Min(Width, Height);
g.DrawImage(result, (drawSize - avatarSize) / 2, (drawSize - avatarSize) / 2);
g.DrawEllipse(rectColor, new Rectangle((drawSize - AvatarSize) / 2, (drawSize - AvatarSize) / 2, AvatarSize, AvatarSize), true, RectSize);
scaleImage.Dispose();
result.Dispose();
return img;
}
protected override void OnPaint(PaintEventArgs e)
{
base.OnPaint(e);
if (RoundImage != null)
{
e.Graphics.DrawImage(RoundImage, 0, 0);
}
else
if (Image == null || FrameIndex < 0 || FrameIndex >= Images.Count)
{
int drawSize = Math.Min(Width, Height);
e.Graphics.FillEllipse(Color.Silver, new Rectangle((drawSize - AvatarSize) / 2, (drawSize - AvatarSize) / 2,
AvatarSize, AvatarSize), true);
}
else
{
e.Graphics.DrawImage(Images[FrameIndex], 0, 0);
}
}
private void timer1_Tick(object sender, EventArgs e)
@ -286,7 +288,6 @@ namespace Sunny.UI
FrameIndex = 0;
}
ShowImage();
Invalidate();
}