C# Gif文件规范-帧的注释属性

C# Gif文件规范-帧的注释属性,c#,comments,gif,specifications,C#,Comments,Gif,Specifications,我期待着在gif文件的每一帧中存储文本的方法。不打印图像中的文本,而是作为属性添加。微软有一个老程序,可以为每一帧设置文本 如您所见,每个帧都有一个字段“Comment” 现在,我的问题是: 该字段是否符合GIF规范?那里几乎没有这样的文件。(事实上有) 如果是: 它位于哪里?在其中一种方法中 有一个项目可以帮你解决这个问题。具体而言,这些文件: ,第87行Encode(),它在代码中指定将内容写入输出gif流的顺序 对于注释扩展,有几个要点: ,第57行GetBuffer(): 内部字节[]

我期待着在gif文件的每一帧中存储
文本的方法。不打印图像中的文本,而是作为属性添加。微软有一个老程序,可以为每一帧设置文本

如您所见,每个帧都有一个字段“Comment”

现在,我的问题是:

该字段是否符合GIF规范?那里几乎没有这样的文件。(事实上有)

如果是:

它位于哪里?在其中一种方法中

有一个项目可以帮你解决这个问题。具体而言,这些文件:

,第87行Encode(),它在代码中指定将内容写入输出gif流的顺序

对于注释扩展,有几个要点:

,第57行GetBuffer():

内部字节[]GetBuffer()
{            
列表=新列表();
list.Add(giftextensions.ExtensionIntroducer);//0x21
list.Add(GifExtensions.CommentLabel);//0xFE
foreach(CommentDatas中的字符串coment)
{
char[]commentCharArray=coment.ToCharArray();
添加((字节)commentCharArray.Length);
foreach(commentCharArray中的字符c)
{
列表.添加((字节)c);
}
}
list.Add(giftextensions.Terminator);//0
return list.ToArray();
}
好吧,有一个项目可以帮你解决这个问题。具体而言,这些文件:

,第87行Encode(),它在代码中指定将内容写入输出gif流的顺序

对于注释扩展,有几个要点:

,第57行GetBuffer():

内部字节[]GetBuffer()
{            
列表=新列表();
list.Add(giftextensions.ExtensionIntroducer);//0x21
list.Add(GifExtensions.CommentLabel);//0xFE
foreach(CommentDatas中的字符串coment)
{
char[]commentCharArray=coment.ToCharArray();
添加((字节)commentCharArray.Length);
foreach(commentCharArray中的字符c)
{
列表.添加((字节)c);
}
}
list.Add(giftextensions.Terminator);//0
return list.ToArray();
}
最好只使用该工具(Microsoft的GIFAnimator,可通过MSDN订阅获得)并查看它通过十六进制查看器生成的内容。把它放在手边,这样你就可以把你看到的和规范联系起来

我创建了一个包含两个8x8帧的非常简单的GIF文件,第一个输入“frame 1”,第二个输入“number 2”。产生了这个十六进制转储:

我用红色突出显示了相关的块。它们符合规范第24节“注释扩展”:

注释扩展名包含以下文本信息: 不是GIF数据流中实际图形的一部分。这是合适的 包括有关图形、学分、说明或任何 其他类型的非控制和非图形数据。注释扩展名 可被解码器忽略,或可保存以供以后处理; 在任何情况下,注释扩展都不应中断或干扰 随着数据流的处理。

此块是可选的;数据流中可能会出现任意数量的数据流

请注意,规范第23节中的21 F9块“Graphic control extension”(图形控制扩展)块是如何跟在每一帧后面的。它描述了图像文件中的每一帧,“延迟时间”值至关重要。然后是2C,一个“图像描述符”块,规范第20节。它包含每帧的图像数据

回答您的具体问题:

该字段是否符合GIF规范

是的,明确如第24节所述。这完全取决于应用程序是否使用它们。它们只是注释性的,对另一个GIF工具或图像消费者来说没有任何特殊意义

它位于哪里?在其中一种方法中

不,该代码不写注释,它只发出21 F9和2C块。只需修改代码,在前面插入21FE块。大概是这样的:

protected void WriteGraphicCtrlExt(string comment)
{
    if (!string.IsNullOrEmpty(comment)) {
       fs.WriteByte(0x21);
       fs.WriteByte(0xfe);
       var bytes = Encoding.ASCII.GetBytes(comment);
       fs.WriteByte((byte)bytes.Length);
       fs.Write(bytes, 0, bytes.Length);
       fs.WriteByte(0);
    }
    // Rest of code
    //...
}
最好只使用该工具(微软的GIFAnimator,可通过MSDN订阅获得)并查看它通过十六进制查看器生成的内容。把它放在手边,这样你就可以把你看到的和规范联系起来

我创建了一个包含两个8x8帧的非常简单的GIF文件,第一个输入“frame 1”,第二个输入“number 2”。产生了这个十六进制转储:

我用红色突出显示了相关的块。它们符合规范第24节“注释扩展”:

注释扩展名包含以下文本信息: 不是GIF数据流中实际图形的一部分。这是合适的 包括有关图形、学分、说明或任何 其他类型的非控制和非图形数据。注释扩展名 可被解码器忽略,或可保存以供以后处理; 在任何情况下,注释扩展都不应中断或干扰 随着数据流的处理。

此块是可选的;数据流中可能会出现任意数量的数据流

请注意,规范第23节中的21 F9块“Graphic control extension”(图形控制扩展)块是如何跟在每一帧后面的。它描述了图像文件中的每一帧,“延迟时间”值至关重要。然后是2C,一个“图像描述符”块,规范第20节。它包含每帧的图像数据

回答您的具体问题:

该字段是否符合GIF规范

是的,明确地说是o
protected void WriteComment(string comment)
{
        fs.WriteByte(0x21);
        fs.WriteByte(0xfe);

        byte[] lenght = StringToByteArray(comment.Length.ToString("X"));

        foreach (byte b in lenght)
        {
            fs.WriteByte(b);
        }

        WriteString(comment);
}
        internal byte[] GetBuffer()
        {            
            List<byte> list = new List<byte>();
            list.Add(GifExtensions.ExtensionIntroducer); // 0x21
            list.Add(GifExtensions.CommentLabel); // 0xFE
            foreach (string coment in CommentDatas)
            {
                char[] commentCharArray = coment.ToCharArray();
                list.Add((byte)commentCharArray.Length);
                foreach (char c in commentCharArray)
                {
                    list.Add((byte)c);
                }
            }
            list.Add(GifExtensions.Terminator); // 0
            return list.ToArray();
        }
protected void WriteGraphicCtrlExt(string comment)
{
    if (!string.IsNullOrEmpty(comment)) {
       fs.WriteByte(0x21);
       fs.WriteByte(0xfe);
       var bytes = Encoding.ASCII.GetBytes(comment);
       fs.WriteByte((byte)bytes.Length);
       fs.Write(bytes, 0, bytes.Length);
       fs.WriteByte(0);
    }
    // Rest of code
    //...
}