问题描述
|
我有以下代码,这些代码使用WPF图像处理API打印图像的元数据:
void Main()
{
Uri imageUri = new Uri(@\"E:\\tmp\\bomb.gif\");
var decoder = BitmapDecoder.Create(imageUri,BitmapCreateOptions.None,BitmapCacheOption.OnLoad);
var f = decoder.Frames[0];
var m = f.Metadata as BitmapMetadata;
DumpMetadata(m);
}
void DumpMetadata(BitmapMetadata Metadata)
{
DumpMetadata(Metadata,0);
}
void DumpMetadata(BitmapMetadata Metadata,int indentLevel)
{
if (Metadata == null)
{
Console.WriteLine (\"(No Metadata)\");
return;
}
string indent = new string(\'\\t\',indentLevel);
foreach (var propertyName in Metadata)
{
object value = Metadata.GetQuery(propertyName);
BitmapMetadata complexProperty = value as BitmapMetadata;
if (complexProperty != null)
{
Console.WriteLine(\"{0}{1} =\",indent,propertyName);
DumpMetadata(complexProperty,indentLevel + 1);
}
else
{
Type type = null;
if (value != null)
type = value.GetType();
Console.WriteLine(\"{0}{1} = {2} ({3})\",propertyName,value,type);
}
}
}
在Windows 7上,它给出正确的结果:
/imgdesc =
/Left = 0 (System.UInt16)
/Top = 0 (System.UInt16)
/Width = 78 (System.UInt16)
/Height = 121 (System.UInt16)
/LocalColorTableFlag = False (System.Boolean)
/InterlaceFlag = False (System.Boolean)
/SortFlag = False (System.Boolean)
/LocalColorTableSize = 7 (System.Byte)
/grctlext =
/disposal = 2 (System.Byte)
/UserInputFlag = False (System.Boolean)
/TransparencyFlag = True (System.Boolean)
/Delay = 10 (System.UInt16)
/TransparentColorIndex = 0 (System.Byte)
但是在Windows XP(SP3)上,gif图像(是否经过动画处理)的Metadata
属性始终为null。
我认为该问题可能与Windows Imaging Component有关,但是WIC应该与SP3一起安装(并且是.NET 3.0的一部分;我在该PC上具有3.5 SP1和4.0),因此它也可以在XP上运行。
不知道这里发生了什么...仅仅是缺少编解码器吗?有没有办法使此代码在XP上有效?
编辑:我需要的信息是3域(帧的持续时间);如果我收不到BitmapMetadata
,还有其他方法可以提取此信息吗?理想情况下,我宁愿只使用WPF图像处理API(即不使用GDI / System.Drawing)。
更新:我在MSDN论坛上发布了相同的问题,根据我收到的答案,只有Windows 7和带有Platform Update的Vista才支持GIF元数据(请参见此处和此处)。因此,我想使用WPF图像API使其无法在XP上运行是不可能的。我可能最终会使用System.Drawing,但是我愿意接受更好的建议...解决方法
没错,问题出在XP中的WIC。该线程还提到了该问题。
但是,使用来自GDI +的旧
System.Drawing
,您可以执行以下操作:
private static int ReadGifDelayInMiliseconds(string gifFile,int frameIndex = 0)
{
System.Drawing.Image img = System.Drawing.Image.FromFile(gifFile);
int numFrames = img.GetFrameCount(FrameDimension.Time);
byte[] bytes = img.GetPropertyItem(0x5100).Value;
if (frameIndex < numFrames)
{
var raw = BitConverter.ToInt32(bytes,frameIndex * 4);
return raw * 10;
}
else
{
return -1;
}
}
注意,由于“ 7”数组具有所有延迟,因此您可以修改函数以一次读取所有帧的延迟。,我最终通过编写一个自定义的GIF解码器解决了这个问题,因为我只需要元数据,所以这并不困难。