How to find where does Image Block start in GIF images?

穿精又带淫゛_ 提交于 2019-11-26 14:51:58

问题


Information source - http://www.onicos.com/staff/iz/formats/gif.html#header

In GIF images the actual image size (width, height) is stored in Image Block. To my best understanding Image Block is the very first block included in header. Before the actual blocks begin, there is a memory allocation called Global Color Table(0..255 x 3 bytes)(from now-on GCT). If I can know the byte count reserved for GCT I can extract bytes 5-9 from Image Block and have the actual image size.

Question: How can I know/learn what is the size of the GCT?

OR

Where does GCT end?

OR

Where does Image Block begin?

OR

Where does Image Block end?


回答1:


All you need for gif enc/dec you will find here 3MF Project GIF

  1. GCT

    this block is optional and not always present in a GIF file. Size is determined by number of colors and bit wide from GIF header. I decode/load it like this:

    struct _hdr
        {
        // Header
        BYTE Signature[3];      /* Header Signature (always "GIF") */
        BYTE Version[3];        /* GIF format version("87a" or "89a") */
        // Logical Screen Descriptor
        WORD xs;
        WORD ys;
        BYTE Packed;            /* Screen and Color Map Information */
        BYTE BackgroundColor;   /* Background Color Index */
        BYTE AspectRatio;       /* Pixel Aspect Ratio */
        } hdr;
    
    gcolor_bits= (hdr.Packed    &7)+1;  // global pallete
    scolor_bits=((hdr.Packed>>4)&7)+1;  // screen
    _gcolor_sorted =hdr.Packed&8;
    _gcolor_table  =hdr.Packed&128;
    scolors=1<<scolor_bits;
    gcolors=1<<gcolor_bits;
    
    • if _gcolor_table is true then GCT is present
    • GCT size is 3*gcolors [Bytes] stored in order R,G,B
  2. Start of Image

    This one is a bit tricky because GIF89a files may contain many optional blocks. You need to do a decoding loop detecting type of block and decoding/skipping it according its purpose. I do it like this:

    struct _gfxext
        {
        BYTE Introducer;        /* Extension Introducer (always 21h) */
        BYTE Label;             /* Graphic Control Label (always F9h) */
        BYTE BlockSize;         /* Size of remaining fields (always 04h) */
        BYTE Packed;            /* Method of graphics disposal to use */
        WORD DelayTime;         /* Hundredths of seconds to wait    */
        BYTE ColorIndex;        /* Transparent Color Index */
        BYTE Terminator;        /* Block Terminator (always 0) */
        } gfx;
    
    struct _txtext
        {
        BYTE Introducer;        /* Extension Introducer (always 21h) */
        BYTE Label;             /* Extension Label (always 01h) */
        BYTE BlockSize;         /* Size of Extension Block (always 0Ch) */
        WORD TextGridLeft;      /* X position of text grid in pixels */
        WORD TextGridTop;       /* Y position of text grid in pixels */
        WORD TextGridWidth;     /* Width of the text grid in pixels */
        WORD TextGridHeight;    /* Height of the text grid in pixels */
        BYTE CellWidth;         /* Width of a grid cell in pixels */
        BYTE CellHeight;        /* Height of a grid cell in pixels */
        BYTE TextFgColorIndex;  /* Text foreground color index value */
        BYTE TextBgColorIndex;  /* Text background color index value */
    //      BYTE *PlainTextData;    /* The Plain Text data */
    //      BYTE Terminator;        /* Block Terminator (always 0) */
        };
    
    struct _remext
        {
        BYTE Introducer;        /* Extension Introducer (always 21h) */
        BYTE Label;             /* Comment Label (always FEh) */
    //      BYTE *CommentData;      /* Pointer to Comment Data sub-blocks */
    //      BYTE Terminator;        /* Block Terminator (always 0) */
        };
    
    struct _appext
        {
        BYTE Introducer;        /* Extension Introducer (always 21h) */
        BYTE Label;             /* Extension Label (always FFh) */
        BYTE BlockSize;         /* Size of Extension Block (always 0Bh) */
        CHAR Identifier[8];     /* Application Identifier */
        BYTE AuthentCode[3];    /* Application Authentication Code */
    //      BYTE *ApplicationData;  /* Point to Application Data sub-blocks */
    //      BYTE Terminator;        /* Block Terminator (always 0) */
        };
    // handle 89a extensions blocks
    _gfxext gfxext; gfxext.Introducer=0;
    _txtext txtext; txtext.Introducer=0;
    _remext remext; remext.Introducer=0;
    _appext appext; appext.Introducer=0;
    
    if((hdr.Version[0]=='8')
     &&(hdr.Version[1]=='9')
     &&(hdr.Version[2]=='a')) _89a=true; else _89a=false;
    
    if (_89a)
     for (;!f.eof;)
        {
        f.peek((BYTE*)&dw,2);
             if (dw==0xF921) { f.read((BYTE*)&gfxext,sizeof(_gfxext)); }
        else if (dw==0x0121) { f.read((BYTE*)&txtext,sizeof(_txtext)); for (;!f.eof;) { f.read(&db,1); if (!db) break; f.read(dat,DWORD(db)); } }
        else if (dw==0xFE21) { f.read((BYTE*)&remext,sizeof(_remext)); for (;!f.eof;) { f.read(&db,1); if (!db) break; f.read(dat,DWORD(db)); } }
        else if (dw==0xFF21) { f.read((BYTE*)&appext,sizeof(_appext)); for (;!f.eof;) { f.read(&db,1); if (!db) break; f.read(dat,DWORD(db)); } }
        else if ((dw&0x00FF)==0x0021) return; // corrupted file
        else break;                           // no extension found
        }
    
    • db is BYTE variable
    • dw is WORD variable
    • f is my file cache class the members are self explanatory I hope anyway:
    • f.read(&data,size) read size BYTES into data
    • f.peek(&data,size) do the same but do not update position in file
    • f.eof indicates end of file reached

    this has to be done for each frame after all this image header starts.

  3. End of Image

    Image block ends with terminator. All the chunks of image start with BYTE count. If it is zero it is a terminator block. Usually after the image there are few BYTES not used by LZW data so after you fill the whole image area skip all blocks until hit the zero sized block and then stop that is image end. If BYTE after this is 0x3B hex you reached the end of GIF file

[notes]

Do not forget to encapsulate struct by #pragma pack(1) and #pragma pack() or manually set align to 1 BYTE. Beware problems with signed data types (LZW data is unsigned) so overtype where you can to avoid problems or use just unsigned variables (with enough bit-width) for decoding



来源:https://stackoverflow.com/questions/32349200/how-to-find-where-does-image-block-start-in-gif-images

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!