* UIGifAvatar: 重写图片刷新流程,减少内存及GC
This commit is contained in:
parent
88d551b5e3
commit
c0ccb4cfd0
@ -17,6 +17,7 @@
|
|||||||
* 创建日期: 2022-07-01
|
* 创建日期: 2022-07-01
|
||||||
*
|
*
|
||||||
* 2022-07-01: V3.2.0 增加文件说明
|
* 2022-07-01: V3.2.0 增加文件说明
|
||||||
|
* 2022-07-25: V3.2.2 重写图片刷新流程,减少内存及GC
|
||||||
******************************************************************************/
|
******************************************************************************/
|
||||||
|
|
||||||
using System;
|
using System;
|
||||||
@ -47,6 +48,7 @@ namespace Sunny.UI
|
|||||||
~UIGifAvatar()
|
~UIGifAvatar()
|
||||||
{
|
{
|
||||||
Active = false;
|
Active = false;
|
||||||
|
Clear();
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
@ -124,7 +126,7 @@ namespace Sunny.UI
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
ShowImage();
|
CalcImages();
|
||||||
Invalidate();
|
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 ConcurrentDictionary<int, Image> Images = new ConcurrentDictionary<int, Image>();
|
||||||
|
|
||||||
private int avatarSize = 120;
|
private int avatarSize = 120;
|
||||||
@ -143,12 +176,11 @@ namespace Sunny.UI
|
|||||||
set
|
set
|
||||||
{
|
{
|
||||||
avatarSize = value;
|
avatarSize = value;
|
||||||
ShowImage();
|
CalcImages();
|
||||||
Invalidate();
|
Invalidate();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
private int ImageCount;
|
private int ImageCount;
|
||||||
public bool IsGif => ImageCount > 0;
|
public bool IsGif => ImageCount > 0;
|
||||||
|
|
||||||
@ -178,97 +210,67 @@ namespace Sunny.UI
|
|||||||
protected override void OnSizeChanged(EventArgs e)
|
protected override void OnSizeChanged(EventArgs e)
|
||||||
{
|
{
|
||||||
base.OnSizeChanged(e);
|
base.OnSizeChanged(e);
|
||||||
ShowImage();
|
CalcImages();
|
||||||
Invalidate();
|
Invalidate();
|
||||||
}
|
}
|
||||||
|
|
||||||
private Image RoundImage;
|
private Image ScaleImage(int frameIndex)
|
||||||
|
|
||||||
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)
|
|
||||||
{
|
{
|
||||||
if (Image == null)
|
if (Image == null)
|
||||||
{
|
{
|
||||||
return 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)
|
if (!IsGif)
|
||||||
{
|
{
|
||||||
Bitmap scaleImage = ((Bitmap)Image).ResizeImage((int)(Image.Width * 1.0 / size + 0.5),
|
scaleImage = ((Bitmap)Image).ResizeImage((int)(Image.Width * 1.0 / size + 0.5), (int)(Image.Height * 1.0 / size + 0.5));
|
||||||
(int)(Image.Height * 1.0 / size + 0.5));
|
result = scaleImage.Split(avatarSize, UIShape.Circle);
|
||||||
Bitmap result = scaleImage.Split(avatarSize, UIShape.Circle);
|
|
||||||
scaleImage.Dispose();
|
|
||||||
return result;
|
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
FrameDimension fd = new FrameDimension(Image.FrameDimensionsList[0]);
|
FrameDimension fd = new FrameDimension(Image.FrameDimensionsList[0]);
|
||||||
Image.SelectActiveFrame(fd, FrameIndex);
|
Image.SelectActiveFrame(fd, frameIndex);
|
||||||
Bitmap imageEx = new Bitmap(Image.Width, Image.Height);
|
Bitmap imageEx = new Bitmap(Image.Width, Image.Height);
|
||||||
Graphics g = Graphics.FromImage(imageEx);
|
Graphics gx = Graphics.FromImage(imageEx);
|
||||||
g.DrawImage(Image, new Point(0, 0));
|
gx.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));
|
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);
|
result = scaleImage.Split(avatarSize, UIShape.Circle);
|
||||||
scaleImage.Dispose();
|
|
||||||
imageEx.Dispose();
|
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)
|
protected override void OnPaint(PaintEventArgs e)
|
||||||
{
|
{
|
||||||
base.OnPaint(e);
|
base.OnPaint(e);
|
||||||
|
if (Image == null || FrameIndex < 0 || FrameIndex >= Images.Count)
|
||||||
if (RoundImage != null)
|
|
||||||
{
|
|
||||||
e.Graphics.DrawImage(RoundImage, 0, 0);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
{
|
||||||
int drawSize = Math.Min(Width, Height);
|
int drawSize = Math.Min(Width, Height);
|
||||||
e.Graphics.FillEllipse(Color.Silver, new Rectangle((drawSize - AvatarSize) / 2, (drawSize - AvatarSize) / 2,
|
e.Graphics.FillEllipse(Color.Silver, new Rectangle((drawSize - AvatarSize) / 2, (drawSize - AvatarSize) / 2,
|
||||||
AvatarSize, AvatarSize), true);
|
AvatarSize, AvatarSize), true);
|
||||||
}
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
e.Graphics.DrawImage(Images[FrameIndex], 0, 0);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private void timer1_Tick(object sender, EventArgs e)
|
private void timer1_Tick(object sender, EventArgs e)
|
||||||
@ -286,7 +288,6 @@ namespace Sunny.UI
|
|||||||
FrameIndex = 0;
|
FrameIndex = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
ShowImage();
|
|
||||||
Invalidate();
|
Invalidate();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user