Question

I'm looking forward for a way to store text in each frame of a gif file. Not printing the text in the image, but adding as a property. There is na old program made by Microsoft that is able to set text for each frame.

Comments

As you can see, there is a field "Comment" for each frame.

Now, my question is:

Is this field something that the GIF specification aproves? There is almost no documents out there, saying so. (Actually, there is)

if yes:

Where is located? In one of these methods?

     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
        }
    }

EDIT:

I've found a way to do it, like the Hans Passand wrote:

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);
}
Was it helpful?

Solution 2

Well there's the GifLib project that may help you with this. Specifically, these files:

http://giflib.codeplex.com/SourceControl/latest#GifEncoder.cs, line #87 Encode(), which specifies, in code, in what order to write things to the output gif stream

and for the comments extensions, a few pointers:

http://giflib.codeplex.com/SourceControl/latest#CommentEx.cs, line #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();
        }

OTHER TIPS

Best to just use the tool (Microsoft's GIFAnimator, available through an MSDN subscription) and see what it produces with a hex viewer. Keep the GIF specification handy so you can correlate what you see with the spec.

I created a very simple GIF file with two 8x8 frames, typed "frame 1" for the first one and "number 2" for the second. Which produced this hex dump:

enter image description here

I highlighted the relevant blocks in red. They match section 24 in the spec, "Comment extension":

The Comment Extension contains textual information which is not part of the actual graphics in the GIF Data Stream. It is suitable for including comments about the graphics, credits, descriptions or any other type of non-control and non-graphic data. The Comment Extension may be ignored by the decoder, or it may be saved for later processing; under no circumstances should a Comment Extension disrupt or interfere with the processing of the Data Stream.

This block is OPTIONAL; any number of them may appear in the Data Stream.

Note how each of them is followed by a 21 F9 block, a "Graphic control extension" block, section 23 in the spec. It describes each frame in the image file, the "delay time" value is crucial. Which is then followed by 2C, a "Image descriptor" block, section 20 in the spec. It contains the image data for each frame.

Answering your specific questions:

Is this field something that the GIF specification aproves?

Yes, explicitly as outlined in section 24. It is entirely up to the app to use them as it sees fit. They are merely annotational and don't mean anything in particular to another GIF utility or image consumer.

Where is located? In one of these methods?

No, that code doesn't write the comment, it only emits the 21 F9 and 2C blocks. Simply alter the code to insert the 21 FE block ahead of it. Something like this:

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
    //...
}
Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top