GIF and LZW
BlitzPlus Forums/BlitzPlus Programming/GIF and LZW
| ||
| 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
|
| ||
| Well I don't know about encoding gif but I converted some C to PB a while ago and have translated it to b+/b3d. http://www.blitzbasic.com/codearcs/codearcs.php?code=2207 How did you get on with your code? |
| ||
| I can't say what's wrong with the code - but thanks for posting the links - I've wanted to do this myself for some time. I'll get back to you if I figure anything out. |