GPS4Palm

Source Code Documentation


giflzw.c

Go to the documentation of this file.
00001 /*****************************************************************************
00002  *
00003  * $RCSfile: giflzw_8c-source.html,v $
00004  *
00005  * LZW decompressing for GIF file reader (gifread.c) 
00006  *
00007  * History:
00008  * 2002-12-15:  first version, taken from the ZBoxZ application suite
00009  *              (Rev. 0.30) by Tom Zerucha
00010  *
00011  * This program is Copyright (C) 12/2002 Matthias Prinke
00012  * <matthias.prinke@surfeu.de> and covered by GNU's GPL.
00013  * In particular, this program is free software and comes WITHOUT
00014  * ANY WARRANTY.
00015  *
00016  *
00017  * $Author: mp $
00018  *
00019  * $Date: 2007-10-08 20:40:33 $
00020  *
00021  * $Revision: 1.7.2.1 $
00022  *
00023  * $Log: giflzw_8c-source.html,v $
00023  * Revision 1.7.2.1  2007-10-08 20:40:33  mp
00023  * updated for gps4palm V0.9.5 beta
00023  *
00024  * Revision 1.2  2005-05-15 10:44:03  mp
00025  * added passing of file descriptor (fd) for fread() to functions
00026  *
00027  * Revision 1.1.1.1  2003/07/14 18:59:29  mp
00028  * Imported GPS4Palm to CVS revision control.
00029  *
00030  *
00031  ****************************************************************************/
00032 #include <PalmOS.h>
00033 #include <PalmCompatibility.h>
00034 #include "stringil.h"
00035 #include "file_io.h"
00036 
00037 static int ZeroDataBlock = 0;
00038 
00039 static int GetDataBlock(FileDescrType fd, unsigned char *buf)
00040 {
00041   unsigned char count;
00042 
00043   count = 0;
00044   fread(fd, &count, 1);
00045   ZeroDataBlock = count == 0;
00046   if (count)
00047     fread(fd, buf, count);
00048 
00049   return count;
00050 }
00051 
00052 /***************************************************************************/
00053 
00054 static int curbit, lastbit, get_done, last_byte;
00055 static int return_clear;
00056 
00057 short int *lwzstack, lwzsp, *table;
00058 
00059 static short int firstcode, oldcode;
00060 
00061 static short int code_size, set_code_size;
00062 static short int max_code, max_code_size;
00063 static short int clear_code, end_code;
00064 
00065 void initLWZ(short int input_code_size)
00066 {
00067   set_code_size = input_code_size;
00068   code_size = set_code_size + 1;
00069   clear_code = 1 << set_code_size;
00070   end_code = clear_code + 1;
00071   max_code_size = 2 * clear_code;
00072   max_code = clear_code + 2;
00073 
00074   curbit = lastbit = 0;
00075   last_byte = 2;
00076   get_done = 0;
00077 
00078   return_clear = 1;
00079   lwzsp = 0;
00080 }
00081 
00082 static unsigned char lzcbuf[280];
00083 
00084 static short int nextCode(FileDescrType fd, short int code_size)
00085 {
00086   int i, j, end;
00087   long ret;
00088 
00089   if (return_clear) {
00090     return_clear = 0;
00091     return clear_code;
00092   }
00093 
00094   end = curbit + code_size;
00095 
00096   if (end >= lastbit) {
00097     int count;
00098 
00099     if (get_done)
00100       return -1;
00101 
00102     lzcbuf[0] = lzcbuf[last_byte - 2];
00103     lzcbuf[1] = lzcbuf[last_byte - 1];
00104 
00105     if ((count = GetDataBlock(fd, &lzcbuf[2])) == 0)
00106       get_done = 1;
00107 
00108     if (count < 0)
00109       return -1;
00110 
00111     last_byte = 2 + count;
00112     curbit = (curbit - lastbit) + 16;
00113     lastbit = (2 + count) * 8;
00114 
00115     end = curbit + code_size;
00116   }
00117 
00118   j = end / 8;
00119   i = curbit / 8;
00120 
00121   if (i == j)
00122     ret = (long) lzcbuf[i];
00123   else if (i + 1 == j)
00124     ret = (long) lzcbuf[i] | ((long) lzcbuf[i + 1] << 8);
00125   else
00126     ret =
00127       (long) lzcbuf[i] | ((long) lzcbuf[i + 1] << 8) | ((long) lzcbuf[i + 2] <<
00128                                                         16);
00129 
00130   ret = (ret >> (curbit % 8)) & (0x7fff >> (15 - code_size));
00131   curbit += code_size;
00132 
00133   return (int) ret;
00134 }
00135 
00136 short int nextLWZ(FileDescrType fd)
00137 {
00138   short int code, incode;
00139   register int i;
00140 
00141   while ((code = nextCode(fd, code_size)) >= 0) {
00142     if (code == clear_code) {
00143 
00144       /* corrupt GIFs can make this happen */
00145       if (clear_code >= 4096)
00146         return -2;
00147 
00148       memset(table,0,16384);
00149       for (i = 0; i < clear_code; ++i)
00150         table[4096+i] = i;
00151 
00152       code_size = set_code_size + 1;
00153       max_code_size = 2 * clear_code;
00154       max_code = clear_code + 2;
00155       lwzsp = 0;
00156       do {
00157         firstcode = oldcode = nextCode(fd, code_size);
00158       } while (firstcode == clear_code);
00159 
00160       return firstcode;
00161     }
00162     if (code == end_code) {
00163       int count;
00164       unsigned char wbuf[260];
00165 
00166       if (ZeroDataBlock)
00167         return -2;
00168 
00169       while ((count = GetDataBlock(fd, wbuf)) > 0);
00170 
00171       return -2;
00172     }
00173 
00174     incode = code;
00175 
00176     if (code >= max_code) {
00177       lwzstack[lwzsp++] = firstcode;
00178       code = oldcode;
00179     }
00180 
00181     while (code >= clear_code) {
00182       lwzstack[lwzsp++] = table[4096+code];
00183       if (code == table[code])
00184         return (code);
00185       if (lwzsp >= 4096 )
00186         return (code);
00187       code = table[code];
00188     }
00189 
00190     lwzstack[lwzsp++] = firstcode = table[4096+code];
00191 
00192     if ((code = max_code) < 4096) {
00193       table[code] = oldcode;
00194       table[4096+code] = firstcode;
00195       ++max_code;
00196       if ((max_code >= max_code_size) && (max_code_size < 4096)) {
00197         max_code_size *= 2;
00198         ++code_size;
00199       }
00200     }
00201 
00202     oldcode = incode;
00203 
00204     if (lwzsp)
00205       return lwzstack[--lwzsp];
00206   }
00207   return code;
00208 }

Created: Mon, 08 Oct 2007 22:33:16 +0200
Copyright ©2004 M. Prinke