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 文件规范 - 帧的注释属性的主要内容,如果未能解决你的问题,请参考以下文章