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

时间:2014-03-06 00:15:07

标签: c# comments gif specifications

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

Comments

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

现在,我的问题是:

  

这个字段是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);
}

2 个答案:

答案 0 :(得分:3)

最好只使用该工具(Microsoft的GIFAnimator,可通过MSDN订阅获得),并查看它使用十六进制查看器生成的内容。保持GIF specification方便,以便您可以将您看到的内容与规范相关联。

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

enter image description here

我用红色突出显示了相关的块。它们与规范中的第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
    //...
}

答案 1 :(得分:1)

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

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

以及评论扩展,一些指示:

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