Anonymous
Как убрать появление белых пятен на значке GIF в wpf?
Сообщение
Anonymous » 18 окт 2025, 14:41
Я создал класс gif, который занимается рендерингом и запуском файлов значков gif в wpf. Тем не менее, во время анимации на гифке продолжают появляться странные белые пятна. Можете ли вы сказать мне, что я могу сделать, чтобы получить разрешение gif без этих мест?
Вот мой код:
Код: Выделить всё
public class Gif : Image
{
private bool _isInitialized;
private GifBitmapDecoder _decoder;
private int _frameIndex = 0;
private DispatcherTimer _timer;
public static readonly DependencyProperty GifSourceProperty =
DependencyProperty.Register(nameof(GifSource), typeof(string), typeof(Gif),
new PropertyMetadata(string.Empty, OnGifSourceChanged));
public static readonly DependencyProperty AutoStartProperty =
DependencyProperty.Register(nameof(AutoStart), typeof(bool), typeof(Gif),
new PropertyMetadata(true, OnAutoStartChanged));
public string GifSource
{
get { return (string)GetValue(GifSourceProperty); }
set { SetValue(GifSourceProperty, value); }
}
public bool AutoStart
{
get { return (bool)GetValue(AutoStartProperty); }
set { SetValue(AutoStartProperty, value); }
}
private static void OnGifSourceChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
{
((Gif)d).Initialize();
}
private static void OnAutoStartChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
{
var gif = (Gif)d;
if ((bool)e.NewValue && gif.Visibility == Visibility.Visible)
{
gif.StartAnimation();
}
}
static Gif()
{
VisibilityProperty.OverrideMetadata(typeof(Gif), new FrameworkPropertyMetadata(VisibilityPropertyChanged));
}
private void Initialize()
{
if (string.IsNullOrEmpty(GifSource))
return;
_decoder = new GifBitmapDecoder(new Uri("pack://application:,,," + this.GifSource), BitmapCreateOptions.PreservePixelFormat, BitmapCacheOption.OnLoad);
this.Source = _decoder.Frames[0];
RenderOptions.SetBitmapScalingMode(this, BitmapScalingMode.HighQuality);
_timer = new DispatcherTimer();
_timer.Tick += Timer_Tick;
_isInitialized = true;
if (AutoStart && this.Visibility == Visibility.Visible)
StartAnimation();
}
private void StartTimerForFrame(int frameIndex)
{
int delay = 100; // default
try
{
var metadata = _decoder.Frames[frameIndex].Metadata as BitmapMetadata;
if (metadata != null)
{
object delayObj = metadata.GetQuery("/grctlext/Delay");
if (delayObj != null)
delay = ((ushort)delayObj) * 10; // 1/100s → ms
}
}
catch { }
_timer.Interval = TimeSpan.FromMilliseconds(delay);
_timer.Start();
}
private void Timer_Tick(object sender, EventArgs e)
{
if (_decoder == null || _decoder.Frames.Count == 0)
return;
var frame = _decoder.Frames[_frameIndex];
var rtb = new RenderTargetBitmap(frame.PixelWidth, frame.PixelHeight, frame.DpiX, frame.DpiY, System.Windows.Media.PixelFormats.Pbgra32);
var dv = new DrawingVisual();
using (var ctx = dv.RenderOpen())
{
ctx.DrawImage(frame, new Rect(0, 0, frame.PixelWidth, frame.PixelHeight));
}
rtb.Render(dv);
this.Source = rtb;
_frameIndex = (_frameIndex + 1) % _decoder.Frames.Count;
StartTimerForFrame(_frameIndex);
}
private static void VisibilityPropertyChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
{
var gif = (Gif)d;
if ((Visibility)e.NewValue == Visibility.Visible)
gif.StartAnimation();
else
gif.StopAnimation();
}
public void StartAnimation()
{
if (!_isInitialized)
Initialize();
GifAnimation(true);
}
public void StopAnimation()
{
GifAnimation(false);
}
private void GifAnimation(bool toStart)
{
if (_timer == null)
return;
if (toStart)
{
_frameIndex = 0;
StartTimerForFrame(_frameIndex);
}
else
{
_timer.Stop();
}
}
protected override Size MeasureOverride(Size availableSize)
{
if (this.Width > 0 && this.Height > 0)
return new Size(this.Width, this.Height);
return base.MeasureOverride(availableSize);
}
}
Результат этого подхода см. на изображении.
Подробнее здесь:
https://stackoverflow.com/questions/797 ... con-in-wpf
1760787661
Anonymous
Я создал класс gif, который занимается рендерингом и запуском файлов значков gif в wpf. Тем не менее, во время анимации на гифке продолжают появляться странные белые пятна. Можете ли вы сказать мне, что я могу сделать, чтобы получить разрешение gif без этих мест? Вот мой код: [code] public class Gif : Image { private bool _isInitialized; private GifBitmapDecoder _decoder; private int _frameIndex = 0; private DispatcherTimer _timer; public static readonly DependencyProperty GifSourceProperty = DependencyProperty.Register(nameof(GifSource), typeof(string), typeof(Gif), new PropertyMetadata(string.Empty, OnGifSourceChanged)); public static readonly DependencyProperty AutoStartProperty = DependencyProperty.Register(nameof(AutoStart), typeof(bool), typeof(Gif), new PropertyMetadata(true, OnAutoStartChanged)); public string GifSource { get { return (string)GetValue(GifSourceProperty); } set { SetValue(GifSourceProperty, value); } } public bool AutoStart { get { return (bool)GetValue(AutoStartProperty); } set { SetValue(AutoStartProperty, value); } } private static void OnGifSourceChanged(DependencyObject d, DependencyPropertyChangedEventArgs e) { ((Gif)d).Initialize(); } private static void OnAutoStartChanged(DependencyObject d, DependencyPropertyChangedEventArgs e) { var gif = (Gif)d; if ((bool)e.NewValue && gif.Visibility == Visibility.Visible) { gif.StartAnimation(); } } static Gif() { VisibilityProperty.OverrideMetadata(typeof(Gif), new FrameworkPropertyMetadata(VisibilityPropertyChanged)); } private void Initialize() { if (string.IsNullOrEmpty(GifSource)) return; _decoder = new GifBitmapDecoder(new Uri("pack://application:,,," + this.GifSource), BitmapCreateOptions.PreservePixelFormat, BitmapCacheOption.OnLoad); this.Source = _decoder.Frames[0]; RenderOptions.SetBitmapScalingMode(this, BitmapScalingMode.HighQuality); _timer = new DispatcherTimer(); _timer.Tick += Timer_Tick; _isInitialized = true; if (AutoStart && this.Visibility == Visibility.Visible) StartAnimation(); } private void StartTimerForFrame(int frameIndex) { int delay = 100; // default try { var metadata = _decoder.Frames[frameIndex].Metadata as BitmapMetadata; if (metadata != null) { object delayObj = metadata.GetQuery("/grctlext/Delay"); if (delayObj != null) delay = ((ushort)delayObj) * 10; // 1/100s → ms } } catch { } _timer.Interval = TimeSpan.FromMilliseconds(delay); _timer.Start(); } private void Timer_Tick(object sender, EventArgs e) { if (_decoder == null || _decoder.Frames.Count == 0) return; var frame = _decoder.Frames[_frameIndex]; var rtb = new RenderTargetBitmap(frame.PixelWidth, frame.PixelHeight, frame.DpiX, frame.DpiY, System.Windows.Media.PixelFormats.Pbgra32); var dv = new DrawingVisual(); using (var ctx = dv.RenderOpen()) { ctx.DrawImage(frame, new Rect(0, 0, frame.PixelWidth, frame.PixelHeight)); } rtb.Render(dv); this.Source = rtb; _frameIndex = (_frameIndex + 1) % _decoder.Frames.Count; StartTimerForFrame(_frameIndex); } private static void VisibilityPropertyChanged(DependencyObject d, DependencyPropertyChangedEventArgs e) { var gif = (Gif)d; if ((Visibility)e.NewValue == Visibility.Visible) gif.StartAnimation(); else gif.StopAnimation(); } public void StartAnimation() { if (!_isInitialized) Initialize(); GifAnimation(true); } public void StopAnimation() { GifAnimation(false); } private void GifAnimation(bool toStart) { if (_timer == null) return; if (toStart) { _frameIndex = 0; StartTimerForFrame(_frameIndex); } else { _timer.Stop(); } } protected override Size MeasureOverride(Size availableSize) { if (this.Width > 0 && this.Height > 0) return new Size(this.Width, this.Height); return base.MeasureOverride(availableSize); } } [/code] Результат этого подхода см. на изображении. [img]https://i.sstatic.net/Jfqwoc32.png[/img] [img]https://i.sstatic.net/oTzEjSDA.png[/img] Подробнее здесь: [url]https://stackoverflow.com/questions/79793736/how-to-remove-white-spots-from-appearing-in-gif-icon-in-wpf[/url]