开发者

Metadata is null for GIF images on Windows XP SP3 (works fine on Windows 7)

开发者 https://www.devze.com 2023-02-27 03:35 出处:网络
I have the following piece of code, which prints the metadata of an image using the WPF imaging API: void Main()

I have the following piece of code, which prints the metadata of an image using the WPF imaging 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})", indent, propertyName, value, type);
        }
    }
}

On Windows 7, it gives correct results:

/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)

But on Windows XP (SP3), the Metadata property is always null for GIF images (animated or not).

I think the issue might be related to Windows Imaging Component, but WIC is supposed to be installed with SP3 (and also as part of .NET 3.0; I have 3.5 SP1 and 4.0 on that PC), so it should work on XP too.

Not sure what's going on here... Is it just a missing codec? Is there a way to make this code work on XP?

EDIT: the information I need is the Delay field (duration of the frame); if I can't get the BitmapMetadata, is there another way to extract this information? Ideally I would prefer to use only the WPF imaging API (i.e. not GDI/System.Drawing).


UPDATE: I posted the same question on the MSDN forums, and according to the answer I received, GIF metadata are only supported on Windows 7, and on Vista with Platform Update (see here and there). So I guess it's just not possible to make it work on XP using the WPF imaging API. I will probably end up using System.Drawing, but I'm open to better suggestions...


You are right, the issue is with WIC in XP. This thread also mentions that problem.

However using the old System.Drawing from GDI+ you could do something like this:

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;
    }       
}

Note that you can modify the function to read the delay of every frame all at once since the bytes array has all the delays.


I eventually solved this by writing a custom GIF decoder, which is not unreasonably hard since I only need the metadata...

0

精彩评论

暂无评论...
验证码 换一张
取 消

关注公众号