Мой предыдущий вопрос является Why GifBitmapDecoder play incomplete gif , и теперь я хочу, чтобы завершить GIF кадры, прежде чем использовать его, как это:Как объединить два растровых кадра в один?
GifBitmapDecoder _gifDecoder = new GifBitmapDecoder(
new Uri("pack://application:,,,/Expression/f006.gif"),
BitmapCreateOptions.PreservePixelFormat, BitmapCacheOption.Default);
BitmapFrame preBF = null;
FrameInfo preFI = null;
foreach (BitmapFrame bf in gifDecoder.Frames)
{
FrameInfo fi = GetFrameInfo(bf);
if (fi.DisposalMethod == FrameDisposalMethod.Combine && preBF != null)
{
// TODO Find a way to combine bf and preBF to makeup a complete gif frame
}
preBF = bf;
preFI = fi;
}
А класс FrameInfo и метод GetFrameInfo являются следующие (спасибо к http://www.thomaslevesque.com/tag/gif/ , но он не работает хорошо в моей работе, так как кадр еще imcomplete и WpfAnimatedGif.dll слишком много памяти):
#region Get the frame information
private class FrameInfo
{
public TimeSpan Delay { get; set; }
public FrameDisposalMethod DisposalMethod { get; set; }
public double Width { get; set; }
public double Height { get; set; }
public double Left { get; set; }
public double Top { get; set; }
public Rect Rect
{
get { return new Rect(Left, Top, Width, Height); }
}
}
private enum FrameDisposalMethod
{
Replace = 0,
Combine = 1,
RestoreBackground = 2,
RestorePrevious = 3
}
private static FrameInfo GetFrameInfo(BitmapFrame frame)
{
var frameInfo = new FrameInfo
{
Delay = TimeSpan.FromMilliseconds(100),
DisposalMethod = FrameDisposalMethod.Replace,
Width = frame.PixelWidth,
Height = frame.PixelHeight,
Left = 0,
Top = 0
};
BitmapMetadata metadata;
try
{
metadata = frame.Metadata as BitmapMetadata;
if (metadata != null)
{
const string delayQuery = "/grctlext/Delay";
const string disposalQuery = "/grctlext/Disposal";
const string widthQuery = "/imgdesc/Width";
const string heightQuery = "/imgdesc/Height";
const string leftQuery = "/imgdesc/Left";
const string topQuery = "/imgdesc/Top";
var delay = GetQueryOrNull<ushort>(metadata, delayQuery);
if (delay.HasValue)
frameInfo.Delay = TimeSpan.FromMilliseconds(10 * delay.Value);
var disposal = GetQueryOrNull<byte>(metadata, disposalQuery);
if (disposal.HasValue)
frameInfo.DisposalMethod = (FrameDisposalMethod)disposal.Value;
var width = GetQueryOrNull<ushort>(metadata, widthQuery);
if (width.HasValue)
frameInfo.Width = width.Value;
var height = GetQueryOrNull<ushort>(metadata, heightQuery);
if (height.HasValue)
frameInfo.Height = height.Value;
var left = GetQueryOrNull<ushort>(metadata, leftQuery);
if (left.HasValue)
frameInfo.Left = left.Value;
var top = GetQueryOrNull<ushort>(metadata, topQuery);
if (top.HasValue)
frameInfo.Top = top.Value;
}
}
catch (NotSupportedException)
{
}
return frameInfo;
}
private static T? GetQueryOrNull<T>(BitmapMetadata metadata, string query)
where T : struct
{
if (metadata.ContainsQuery(query))
{
object value = metadata.GetQuery(query);
if (value != null)
return (T)value;
}
return null;
}
#endregion
Итак, есть ли способ реализовать TODO?
Возможно, [это] (http://stackoverflow.com/a/20024774/1136211) доставит вас в правильном направлении. – Clemens
Это действительно работает! Но прозрачность источника пропущена ... Как с этим бороться? – Chobits
Вы имеете в виду, что вы копируете растровое изображение с прозрачным фоном поверх другого, которое также имеет прозрачный фон? – Clemens