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

Posted

技术标签:

【中文标题】Gif 文件规范 - 帧的注释属性【英文标题】:Gif File Specification - Comment property of frames 【发布时间】:2014-04-08 08:50:05 【问题描述】:

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

如您所见,每一帧都有一个“评论”字段。

现在,我的问题是:

这个字段是 GIF 规范认可的吗?那里几乎没有文件,是这样说的。 (其实是有的)

如果是:

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

     protected void WriteGraphicCtrlExt()
     
    fs.WriteByte(0x21); // extension introducer
    fs.WriteByte(0xf9); // GCE label
        fs.WriteByte(4); // data block size

        int transp, disp;

    if (transparent == Color.Empty) 
    
    transp = 0;
    disp = 0; // dispose = no action
     
    else 
    
    transp = 1;
    disp = 2; // force clear if using transparent color
        

        //If first frame, no transparency and no dispose.
        if (firstFrame)
        
            disp = 0;
            transp = 0;
        
        else
        
            if (dispose >= 0)
            
                disp = dispose & 7; // user override
            
            disp <<= 2;
        

        // packed fields
        fs.WriteByte( Convert.ToByte( 0 | // 1:3 reserved
            disp | // 4:6 disposal
            0 | // 7   user input - 0 = none
            transp )); // 8   transparency flag

        WriteShort(delay); // delay x 1/100 sec
        fs.WriteByte( Convert.ToByte( transIndex)); // transparent color index
        fs.WriteByte(0); // block terminator
    


    protected void WriteImageDesc()
    

        fs.WriteByte(0x2c); // image separator
        WriteShort(0); // image position x,y = 0,0
        WriteShort(0);
        WriteShort(width); // image size
        WriteShort(height);
        // packed fields
        if (firstFrame) 
        
            // no LCT  - GCT is used for first (or only) frame
            fs.WriteByte(0);
         
        else 
        
            // specify normal LCT
            fs.WriteByte( Convert.ToByte( 0x80 | // 1 local color table  1=yes
                0 | // 2 interlace - 0=no
                0 | // 3 sorted - 0=no
                0 | // 4-5 reserved
                palSize ) ); // 6-8 size of color table
        
    

编辑:

我已经找到了一种方法,就像 Hans Passand 写的那样:

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

【问题讨论】:

你看过the GIF specification的第24节吗? 是的,已经找到方法了。 【参考方案1】:

最好只使用该工具(Microsoft 的 GIFAnimator,可通过 MSDN 订阅获得)并使用十六进制查看器查看它产生的效果。将GIF specification 放在手边,以便将您看到的内容与规范关联起来。

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

我用红色突出显示了相关块。它们与规范中的第 24 节“评论扩展”相匹配:

评论扩展包含文本信息 不是 GIF 数据流中实际图形的一部分。很合适 包括有关图形、学分、描述或任何 其他类型的非控制和非图形数据。评论扩展 可能会被解码器忽略,也可能会被保存以供以后处理; 在任何情况下,评论扩展都不应破坏或干扰 处理数据流。 这个块是可选的;任意数量的它们都可能出现在数据流中。

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

回答您的具体问题:

这个字段是 GIF 规范认可的吗?

是的,如第 24 节所述。完全取决于应用程序在其认为合适的情况下使用它们。它们只是注释性的,对其他 GIF 实用程序或图像消费者没有任何特殊意义。

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

不,该代码不写注释,它只发出 21 个 F9 和 2C 块。只需更改代码以在其前面插入 21 FE 块。像这样的:

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

【讨论】:

【参考方案2】:

嗯,GifLib 项目可以帮助您解决这个问题。具体来说,这些文件:

http://giflib.codeplex.com/SourceControl/latest#GifEncoder.cs,第 87 行 Encode(),在代码中指定将内容写入输出 gif 流的顺序

对于 cmets 扩展,一些提示:

http://giflib.codeplex.com/SourceControl/latest#CommentEx.cs,第 57 行 GetBuffer():

        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();
        

【讨论】:

以上是关于Gif 文件规范 - 帧的注释属性的主要内容,如果未能解决你的问题,请参考以下文章

JAVA编程规范-注释规范

Java编码规范

Java基础——注释规范

《从零开始学Swift》学习笔记(Day 57)——Swift编码规范之注释规范:

CSS代码书写规范

CSS代码书写规范