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. |