Here is an excellent read on GIF data structure:
http://giflib.sourceforge.net/whatsinagif/lzw_image_data.html
I programmed a GIF editor of sorts in powershell.
Code here:
https://github.com/timkscripts/PowershellGif/blob/master/gifs.ps1
Explanation
If you imagine a GIF is just a file with blocks of data. Data that is just 0’s and 1’s. We will mostly be looking at the hex side of things, and dealing with bytes.
If you are working with gifs, you might see a gif built like this
[GIF Header][Logical Screen Descriptor][Global Color Table][Application Extension][Comment Extension][Graphics Control Extension][Image Descriptor][Image Data][end of file]
Now, for each image frame, you probably have:
[Comment Extension][Graphics Control Extension][Image Descriptor][Image Data]
repeating for each frame, so your file might look more like this:
[GIF Header][Logical Screen Descriptor][Global Color Table][Application Extension][Comment Extension]
[Graphics Control Extension][Image Descriptor][Image Data]
[Graphics Control Extension][Image Descriptor][Image Data]
[Graphics Control Extension][Image Descriptor][Image Data]
[Graphics Control Extension][Image Descriptor][Image Data]
[Graphics Control Extension][Image Descriptor][Image Data]
[Graphics Control Extension][Image Descriptor][Image Data]
[Graphics Control Extension][Image Descriptor][Image Data]
[Graphics Control Extension][Image Descriptor][Image Data]
[end of file]
So here is my example GIF file:
It’s a character from the video game donkey kong country.
Now, a GIF stores what’s called a color table where it stores each color in the GIF.
So if the GCT has say..5 colors, the Image data of your gif would just be like
1,2,2,2,1,3,4,2,5,2,1,4 etc
basically where 1 is the first color in your table, rather than the gif having RGB values over and over like this:
[01,FF,03],. . . . . . . . , [04,EF,03]
it now looks like
1……………………………3
or something.
So the first lesson of the day is, what happens in my GIF if I set all of my global color values to 0?
well.. this
So I wrote some code that reads each byte of a gif file, and trys to fill in the data of each section of the .GIF.
Some blocks of data are a static size, and other blocks of data get its dynamic size from other blocks of data.
So here is all of my blocks in variable form
# Header Variables
$head_sig = “”;
$head_ver = “”;#Logical Screen Descriptors
$LSD_width = “”;
$LSD_height = “”;
$LSD_PackedField = “”;
$LSD_BackgroundColorIndex = “”;
$LSD_PixelAspectRatio = “”;#Packed Field values for LSD
$LSD_PF_GCTF = “”; #global color table flag
$LSD_PF_CR = “”; #color resolution
$LSD_PF_SF = “”; #sort flag
$LSD_PF_SGCT = “”; #size of global color table#Global Color Table
$GCT_size = 6;
$GCT_bytes = “”;#Graphics Control Extension
$GCE_Intro = “”; #21;
$GCE_GCL = “”; #graphic control label
$GCE_ByteSize = “”;
$GCE_PackedField = “”;
$GCE_DelayTime = “”;
$GCE_TransCI = “”; #transparent color index
$GCE_BlockTerminator = “”;#Packed Field Values for GCE
#Application Extension
$AE_GEC = “”; #21, graphical extension code
$AE_AEL = “”; #FF, application extension Label
$AE_LAP = “”; #0B, length of application block
$AE_Netscape = “”; #8 bytes that spell “NETSCAPE”
$AE_Ver = “”; #”2.0″ version bytes
$AE_LDSB = “”; #length of data sub-block, starts with 0x03 and the next 3 bytes to follow
$AE_One = “”;#0x01, not sure what this is
$AE_LoopCounter = “”; #0 to 65,535… 0 is unlimited
$AE_Terminator = “”; #HEX 0x00, data sub block terminator#Comment Extension
$CE_EI = “”; #Extension introducter, 21
$CE_CL = “”; #comment label, FE
$CE_ByteCount = “”; #number of bytes in sub block
$CE_Bytes = “”; #comment bytes ascii
$CE_Terminator = “”; #terminates CE block, 0x00#Plain Text Extension
$PTE_EI = “”; #Extension Introducter, always 21
$PTE_PTL = “”; #plain text label, always 01
$PTE_ByteCount = “”; #block size, amount of bytes until actual text begins (how many bytes to skip)
$PTE_DSB = “”; #Data sub block
$PTE_Terminator = “”; #terminator, always 0x00#Extension verifier
$GCE_bool = $false; #graphics control extension
$AE_bool = $false; #application extension
$CE_bool = $false; #comment extension
$PTE_bool = $false; #plain text extension
$ID_bool = $false; #Image Descriptor
$Data_bool = $false; #image data
$Data_bool2 = $false;#Image Descriptor
$ID_IS = “”; #Image Seperator
$ID_IL = “”; #Image Left
$ID_IT = “”; #Image Top
$ID_IW = “”; #image width
$ID_IH = “”; #Image Height
$ID_PackedField = “”;#Image Data
$Data_LZW = “”; #minimum code size
$Data_ByteSize = -1; #the number of bytes of data in the sublock (01-ff)
$Data_TempByteSize = 0;
$Data_Image = “”; #The image data
$Data_ImageEnd = “”; #The last digit of every data_image is 00,
$Data_Terminator = “”; #The terminator to the image data is 00
So now that I know what bytes are part of what data blocks, its very easy to say “well, if your adding global table colors to the GCT… instead, write the byte value 0 for R-G-B values. (0,0,0) in RGB is black…
Applying whatever algorithm I Want to the local color tables I can get a variety of effects. Below are some examples:
Sorry for all of the gifs, I had a lot of fun with this.
- Characters used in images are copy right to their respective owners.