GIF and LZW

BlitzPlus Forums/BlitzPlus Programming/GIF and LZW

The forum is locked. These are the original blitzbasic.com forums, kept so they can still be read. No new topics, replies or edits can be made here. To join in, head over to the Blitz3D+ forums.

Ok, I am trying to write a GIF editor. So I need to encode and decode GIF files... I have writen the code below based on a few tutorials I have found. I can open a GIF, read all the headers fine but all I get is static for an image the error is somewhere in the LZW decompression. Can anyone help?

Here are some refferences I found:
http://stars.hybd.net/developer/lzw.php#compression
http://www.w3.org/Graphics/GIF/spec-gif87.txt
http://en.wikipedia.org/wiki/LZW

Type GIF_FILE
	Field w
	Field h
	Field pf
	Field gFlg
	Field cRes
	Field sort
	Field size
	Field gPallet 
	Field frst.GIF_IMG
End Type

Type GIF_IMG
	Field x 
	Field y 
	Field w 
	Field h 
	Field mixed		
	Field lmFlg 	
	Field iFlg 		
	Field lSize 	
	Field imgBank 
	Field img 		
	Field lpallet 	
End Type

Global LZW_rCount
Global LZW_rValue
Global LZW_byteSize
Global LZW_codeSize 
Global LZW_table$[4100]
Global LZW_tIndex


Graphics 800, 600

file = ReadFile(RequestFile("Gif..", "gif", False))
	gf.GIF_FILE = Load_GIFHeader(file) ; 
	While Not Eof(file)
		Select ReadByte(file) ; ............................ search for image discriptor
			Case $2C ; Image	
			gI.GIF_IMG = Load_ImageDescriptor(file)
			If gI\lPallet = 0 Then gI\lPallet = gf\gPallet
			; Clear LZW tables
			For i = 0 To 4099
				LZW_table[i] = ""
			Next
			Stop
			; set code size
			If gI\lmFlg Then 
				LZW_byteSize = gI\lSize
				LZW_codeSize = gI\lSize
			Else
				LZW_byteSize = gF\size
				LZW_codeSize = gF\size
			EndIf
			
			First_Code = get_codeChr(file)
			PokeByte  gI\imgBank, imgIndex, First_Code
			imgIndex = imgIndex + 1
			
			While True 
 				next_code = get_codeChr(file)
				
 				If Codeword = (2 ^ LZW_codeSize) Then; clear code
  					; Clear LZW tables
					For i = 0 To 4099
						LZW_table[i] = ""
					Next
					Stop
					LZW_byteSize = LZW_codeSize
					First_Code = get_codeChr(file)
				ElseIf CodeWord = (2 ^ LZW_codeSize) + 1 Then; end of image
   					Stop
					Exit
				Else
     				inTable = True
					If next_code > 255 Then
						If LZW_table[next_code - 256] = "" Then inTable = False
					EndIf
					
					If Not inTable Then 
					;If Next_Code is Not in the String table Then
						String_buffer$ = get_codeWord(First_code) + Mid(get_codeWord(First_code), 1,1)
						;String_Buffer = translated First_code + 
    					;First byte of First_Code
					Else
						; String_Buffer = Translation of Next_Code
						String_buffer = get_codeWord(Next_code)
						; add translated First_code + First byte of First_Code to the table 
						If LZW_tIndex < 4095 Then
							LZW_table[LZW_tIndex] = get_codeWord(First_code) + Mid(get_codeWord(First_code), 1,1)
							LZW_tIndex = LZW_tIndex + 1
						EndIf
						
						First_Code = Next_Code
						; display String_Buffer
						For i = 1 To Len(String_buffer)
							PokeByte gI\imgBank, imgIndex, Asc(Mid(String_Buffer, i, 1))
							imgIndex = imgIndex + 1
							If imgIndex = gI\w * gI\h Then Goto done
						Next
					EndIf 
  				EndIf
				
				If next_code = (LZW_byteSize ^2) -1  And LZW_byteSize < 12 Then 
					LZW_byteSize = LZW_ByteSize + 1 
				EndIf
			Wend
		End Select 
		.done
		render_palletedImg(gI\lPallet, gI\imgBank, gI\img)
		SetBuffer BackBuffer()
		Cls
			DrawBlock gI\img, 100, 100
		Flip		
		WaitKey()
	Wend
	
Function get_codeWord$(codeChr)
	If codeChr < 256 Then 
		Return Chr(codeChr)
	ElseIf codeChr > 4095 Then
		RuntimeError "Code Character exceeds the 12 bit limit"
	Else
		Return LZW_table[codeChr - 256] 
	EndIf
End Function

Function Load_ImageDescriptor.GIF_IMG(file)
	x = ReadShort(file)
	y = ReadShort(file)
	w = ReadShort(file)
	h = ReadShort(file)
	mixed = ReadByte(file)
	
	lmFlg = mixed Shr 7 				; local map flag
	iFlg = (mixed And 64) Shr 6 		; interlaced image flag
	lSize = (pf And 7) + 1	 			; bits per pixel
	imgBank = CreateBank(w * h)			; buffer to hold img indexes
	img = CreateImage(w, h)
			
	; load local pallet if one exists
	If lmFlg Then
		lpallet = CreateBank(3 * (2 ^ lSize))
		For i = 0 To lSize - 1
			PokeByte lpallet, i, ReadByte(file)
		Next	
	EndIf
	
	; Create data type
	g.GIF_IMG = New GIF_IMG
	g\x = x
	g\y = y
	g\w = w
	g\h = h
	g\mixed		= mixed
	g\lmFlg 	= lmFlg
	g\iFlg 		= iFlg
	g\lSize 	= lSize
	g\imgBank   = imgBank
	g\img 		= img
	g\lpallet 	= lpallet
	Return g
End Function	
	
Function Load_GIFHeader.GIF_FILE(file)
	; Read Header
	For i = 1 To 6						; read 6byte signature
		sig$ = sig + Chr(ReadByte(file))
	Next
	sig = Lower(sig)
	If Instr(sig, "gif") = 0 Then
		CloseFile file
		Return Null
	EndIf
		
	w = ReadShort(file) 				; image width
	h = ReadShort(file) 				; image height
	pf = ReadByte(file)					; packed field
	bg = ReadByte(file) 				; background color
	pa = ReadByte(file) 				; pixel aspect ratio
	
	; Unpack packed field
	gFlg = pf Shr 7						; global color pallet flag
	cRes = ((pf And 112) Shr 4) + 1		; color resolution
	sort = (pf And 8) Shr 3				;
	size = ((pf And 7) + 1)			 	; global pallet size in bytes 
	
	; Read global pallet each color is made of 3 bytes for red, green and blue
	If gFlg Then 
		gPallet = CreateBank(3 * (2 ^ size))
		For i = 0 To  (3 * (2 ^ size))- 1
			PokeByte gPallet, i, ReadByte(file)
		Next
	EndIf
	
	; Create Type
	g.GIF_FILE = New GIF_FILE
	g\w = w
	g\h = h
	g\pf = pf
	g\gFlg = gFlg
	g\cRes = cRes
	g\sort = sort
	g\size = size
	g\gPallet = gPallet
	Return g
End Function


Function get_codeChr(file)
	While LZW_rCount < LZW_byteSize ; keep reading bytes from file till you have enough bits
		nByte = ReadByte(file)	; read the next byte
		LZW_rCount = LZW_rCount + 8 ; increment bit count by 8 (8 bits per byte)
		LZW_rvalue = (LZW_rValue Shl 8) Or nByte
	Wend
	

	
	r = (LZW_rCount - LZW_byteSize)
	For i = 0 To r
		rMask = rMask + (2 ^ i)
	Next
	For i = 0 To (32 - r)
		rvMask = rvMask + (2 ^ i)
	Next 
	rvMask = rvMask Shl r
	
	chrCode = (LZW_rValue And rMask) Shr r
	LZW_rValue = LZW_rValue And rvMask
	
	If chrCode = (2 ^ LZW_byteSize) Then LZW_byteSize = LZW_byteSize + 1
	LZW_rCount = LZW_rCount - LZW_byteSize
	Return chrCode
End Function

Function render_palletedImg(pallet, bank, img)
	w = ImageWidth(img)
	h = ImageHeight(img)
	pSize = BankSize(pallet)
	bSize = BankSize (bank)
	LockBuffer ImageBuffer(img)
	For y = 0 To h - 1
		For x = 0 To w - 1
			ci = PeekByte(bank, bOffset) * 3
			r = PeekByte(pallet, ci)
			g = PeekByte(pallet, ci + 1)
			b = PeekByte(pallet, ci + 2)
			WritePixelFast x, y, return_Color(r, g, b, 255), ImageBuffer(img)
			bOffset = bOffset + 1	
		Next
	Next
	UnlockBuffer ImageBuffer(img)
	Return img
End Function

Function return_Color(r, g, b, a)
	colour = b + (g Shl 8) + (r Shl 16) + (a Shl 24)
	Return colour
End Function