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 }