C# MonoMac System.Drawing.Image.GetPropertyItem(0x5100)

C# MonoMac System.Drawing.Image.GetPropertyItem(0x5100),c#,image,mono,gdi,system.drawing,C#,Image,Mono,Gdi,System.drawing,最近,我试图回答另一个关于加载动画GIFs的帧(位图和持续时间)的问题。该代码可在上找到 在将此代码移到我的dev库之前对其进行其他测试时,我注意到这行代码有一个问题: //Get the times stored in the gif //PropertyTagFrameDelay ((PROPID) 0x5100) comes from gdiplusimaging.h //More info on http://msdn.microsoft.com/en-us/library/window

最近,我试图回答另一个关于加载动画
GIFs
的帧(位图和持续时间)的问题。该代码可在上找到

在将此代码移到我的dev库之前对其进行其他测试时,我注意到这行代码有一个问题:

//Get the times stored in the gif
//PropertyTagFrameDelay ((PROPID) 0x5100) comes from gdiplusimaging.h
//More info on http://msdn.microsoft.com/en-us/library/windows/desktop/ms534416(v=vs.85).aspx
var times = img.GetPropertyItem(0x5100).Value;
在Windows.Net上使用this()运行此命令时,数组的大小与动画
GIF
中的帧数相同,并填充了帧的持续时间。在本例中,字节[20]转换为(BitConverter.ToInt32())5持续时间:

[75,0,0,0,125,0,0,0,125,0,0,0,125,0,0,0,250,0,0,0]
但是,在MonoMac上,同一示例GIF的这行代码返回一个
字节[4]
,该字节仅转换为一个持续时间(第一个):

我测试了10种不同的
GIF
,结果总是一样的。在Windows上,所有持续时间都在字节[]中,而MonoMac仅列出第一个持续时间:

[x,0,0,0]
[75,0,0,0]
[50,0,0,0]
[125,0,0,0]
查看Mono
System.Drawing.Image
,长度似乎是用这个方法设置的,它是一个包装器:


然而,我并没有发现任何问题,源代码和我的实现都没有问题。我是遗漏了什么还是这是一个bug?

我也没有发现mono源代码中有任何错误。如果您发布了一张您尝试过的示例图像,这会很有帮助。GIF图像格式的一个怪癖是,包含帧时间的图形控制扩展块是可选的,可以在图像描述符之前省略。非零概率因此,如果GIF文件只有一个GCE应用于所有帧,则应该对每个帧应用相同的帧时间

请注意,您没有得到4个值,帧时间被编码为32位值,您看到的是字节[]中的小endian编码。您应该使用BitConverter.ToInt32(),正如您在示例代码中正确使用的那样

因此,我认为您可能应该使用以下内容:

//convert 4 bit value to integer
var duration = BitConverter.ToInt32(times, 4*i % times.Length);
请注意,关于GIF帧还有另一个令人讨厌的实现细节,帧#2及以上不必与帧#1大小相同。每一帧都有一个元数据字段,用于描述如何使用前一帧将其与下一帧合并。据我所知,没有属性ID可以获取每个帧的帧偏移量、大小和undraw方法。我认为您需要自己将每个帧渲染成位图,以获得正确的图像序列。非常难看的细节,GIF需要消失。

如果您看到属性总是从活动位图读取:

if (gdip_bitmapdata_property_find_id(image->active_bitmap, propID, &index) != Ok) {

您可以通过调用设置活动位图,然后mono将逐个返回正确的持续时间。由于这与windows不兼容,我称之为mono bug。作为一个简单的解决方法,您当然可以检查数组长度并处理这两种情况。这比检查mono要好,因为如果mono得到修复,它将继续工作。

确实是令人讨厌的细节。这是我在Windows上尝试过的,但在MonoMac上并没有。对于这个GIF,Windows上的
时间
变量是
字节[20]={75,0,0,0125,0,0,0,0125,0,0,0250,0,0,0}
,而MonoMac上的
字节[4]={75,0,0,0,0}
。如前所述,我尝试在Windows上使用的所有GIF,所以我想这不是GIF的怪癖之一,而是Mono的问题?是的,不能将其扫到地板垫下。我相信你会在Mono GDI Plus实现中找到答案。我看了一下,但我没有gif编解码器方面的专业知识来破译正在发生的事情。下面是我发现的一些东西。打电话进来。libgdiplus中有加载图像的函数。文件内部的函数
gdip\u load\u gif\u image
用于加载gif图像。您需要查看
gdip\u load\u gif\u image
内部的情况。正如我所提到的,这是图像加载/解码的地方,我猜bug就在这里。我没有gif方面的专业知识来弄清楚到底发生了什么。祝你好运。这非常有效,谢谢你的跨平台兼容性建议。
//convert 4 bit value to integer
var duration = BitConverter.ToInt32(times, 4*i % times.Length);
if (gdip_bitmapdata_property_find_id(image->active_bitmap, propID, &index) != Ok) {