//----------------------------------- //--- 010 Editor v2.0 Binary Template // // File: BMGIFTemplate.bt // Author: Berend-Jan "SkyLined" Wever // Revision: 1.1 // Purpose: Defines a template for // parsing GIF image files. // SweetScape: Added bug fixes for // reading global color table (May 2nd, 2007) // SweetScape: Added bug fixes for // reading local color table and // changed ReadShort to ReadUShort (Sept 25, 2007) //----------------------------------- // From GIF89a Specification: // ::= Header * Trailer // ::= Logical Screen Descriptor [Global Color Table] // ::= | // ::= [Graphic Control Extension] // ::= | Plain Text Extension // ::= Image Descriptor [Local Color Table] Image Data // ::= Application Extension | Comment Extension LittleEndian(); typedef struct { UBYTE R; UBYTE G; UBYTE B; } RGB ; string ReadRGB( RGB &color ) { string s; SPrintf( s, "#%02X%02X%02X", color.R, color.G, color.B ); return s; } typedef struct { local UBYTE size = ReadUByte(FTell()); while (size != 0) { struct DATASUBBLOCK { UBYTE Size; char Data[size]; } DataSubBlock; size = ReadUByte(FTell()); } UBYTE BlockTerminator; } DATASUBBLOCKS; typedef struct { char Signature[3]; char Version[3]; } GIFHEADER; typedef struct { ushort Width; ushort Height; BitfieldLeftToRight(); struct LOGICALSCREENDESCRIPTOR_PACKEDFIELDS { UBYTE GlobalColorTableFlag : 1; UBYTE ColorResolution : 3; UBYTE SortFlag : 1; UBYTE SizeOfGlobalColorTable : 3; } PackedFields; UBYTE BackgroundColorIndex; UBYTE PixelAspectRatio; } LOGICALSCREENDESCRIPTOR; // ::= Header * Trailer // Header SetBackColor( 0xFFFFFF ); GIFHEADER GifHeader; if( GifHeader.Signature != "GIF" ) { Warning( "File is not a valid GIF. Template stopped." ); return -1; } // ::= Logical Screen Descriptor [Global Color Table] // Logical Screen Descriptor SetBackColor( 0xE0E0E0 ); LOGICALSCREENDESCRIPTOR LogicalScreenDescriptor; // [Global Color Table] if (LogicalScreenDescriptor.PackedFields.GlobalColorTableFlag == 1) { SetBackColor( 0xC0C0C0 ); struct GLOBALCOLORTABLE { local int i; local int size = 1; for (i = 0; i <= LogicalScreenDescriptor.PackedFields.SizeOfGlobalColorTable; i++) { size *= 2; } RGB rgb[size]; } GlobalColorTable ;; } // ::= | SetBackColor( 0xFFFFFF ); struct DATA { while (ReadUByte(FTell()) != 0x3B) { // ::= [Graphic Control Extension] if (ReadUByte(FTell()) == 0x2C) { SetBackColor( 0xE0FFE0 ); struct IMAGEDESCRIPTOR { UBYTE ImageSeperator; ushort ImageLeftPosition; ushort ImageTopPosition; ushort ImageWidth; ushort ImageHeight; struct IMAGEDESCRIPTOR_PACKEDFIELDS { UBYTE LocalColorTableFlag : 1; UBYTE InterlaceFlag : 1; UBYTE SortFlag : 1; UBYTE Reserved : 2; UBYTE SizeOfLocalColorTable : 3; } PackedFields; } ImageDescriptor; if (ImageDescriptor.PackedFields.LocalColorTableFlag == 1) { SetBackColor( 0xC0FFC0 ); struct LOCALCOLORTABLE { local int i; local int size = 1; for (i = 0; i <= ImageDescriptor.PackedFields.SizeOfLocalColorTable; i++) { size *= 2; } RGB rgb[size]; } LocalColorTable ;; } SetBackColor( 0xA0FFA0 ); struct IMAGEDATA { UBYTE LZWMinimumCodeSize; DATASUBBLOCKS DataSubBlocks; } ImageData; } else if (ReadUShort(FTell()) == 0xF921) { SetBackColor( 0xC0FFFF ); struct GRAPHICCONTROLEXTENSION { UBYTE ExtensionIntroducer; // 0x21 UBYTE GraphicControlLabel; // 0xF9 struct GRAPHICCONTROLSUBBLOCK { UBYTE BlockSize; struct GRAPHICCONTROLEXTENSION_DATASUBBLOCK_PACKEDFIELDS { UBYTE Reserved : 3; UBYTE DisposalMethod : 3; UBYTE UserInputFlag : 1; UBYTE TransparentColorFlag : 1; } PackedFields; ushort DelayTime; UBYTE TransparentColorIndex; } GraphicControlSubBlock; UBYTE BlockTerminator; } GraphicControlExtension; } else if (ReadUShort(FTell()) == 0xFE21) { SetBackColor( 0xFFFFC0 ); struct COMMENTEXTENSION { UBYTE ExtensionIntroducer; // 0x21 UBYTE CommentLabel; // 0xFE DATASUBBLOCKS CommentData; } CommentExtension; } else if (ReadUShort(FTell()) == 0x0121) { SetBackColor( 0xC0C0C0 ); struct PLAINTEXTEXTENTION { UBYTE ExtensionIntroducer; // 0x21 UBYTE PlainTextLabel; // 0x01 struct PLAINTEXTSUBBLOCK { UBYTE BlockSize; ushort TextGridLeftPosition; ushort TextGridTopPosition; ushort TextGridWidth; ushort TextGridHeight; UBYTE CharacterCellWidth; UBYTE CharacterCellHeight; UBYTE TextForegroundColorIndex; UBYTE TextBackgroundColorIndex; } PlainTextSubBlock; DATASUBBLOCKS PlainTextData; } PlainTextExtension; } else if (ReadUShort(FTell()) == 0xFF21) { SetBackColor( 0xC0C0FF ); struct APPLICATIONEXTENTION { UBYTE ExtensionIntroducer; // 0x21 UBYTE ApplicationLabel; // 0xFF struct APPLICATIONSUBBLOCK { UBYTE BlockSize; char ApplicationIdentifier[8]; char ApplicationAuthenticationCode[3]; } ApplicationSubBlock; DATASUBBLOCKS ApplicationData; } ApplicationExtension; } else { SetBackColor( 0xFF8080 ); struct UNDEFINEDDATA { UBYTE ExtensionIntroducer; // 21 UBYTE Label; // F9 DATASUBBLOCKS DataSubBlocks; } UndefinedData; } } } Data; SetBackColor( 0xFFFFFF ); struct TRAILER { UBYTE GIFTrailer; } Trailer;