00001 /***************************************************************************** 00002 * 00003 * $RCSfile: gifread_8c-source.html,v $ 00004 * 00005 * GIF Image Decoder 00006 * 00007 * created: 2002-12-15 00008 * 00009 * History: 00010 * 2007-07-11: testing feature NOPROGRESSBAR 00011 * 2002-12-15: imported from the program PiNGer which is 00012 * part of the ZBoxZ application suite (Rev. 0.30) 00013 * by Tom Zerucha. 00014 * 2002-12-29: fixed cleanGIF() to work when called after early abort, 00015 * added skipping of Extension Blocks (optional in GIF89a), 00016 * added abort decoding (pen down event) 00017 * 2002-12-30: added progress bar, modified status messages 00018 * 00019 * This program is Copyright (C) 12/2002 Matthias Prinke 00020 * <matthias.prinke@surfeu.de> and covered by GNU's GPL. 00021 * In particular, this program is free software and comes WITHOUT 00022 * ANY WARRANTY. 00023 * 00024 * Changes for Palm TX are Copyright (C) 07/2007 Frank Saurbier 00025 * <frank.saurbier@surfeu.de> and covered by GNU's GPL. 00026 * In particular, this program is free software and comes WITHOUT 00027 * ANY WARRANTY. 00028 * 00029 * $Author: mp $ 00030 * 00031 * $Date: 2007-10-08 20:40:33 $ 00032 * 00033 * $Log: gifread_8c-source.html,v $ 00033 * Revision 1.7.2.1 2007-10-08 20:40:33 mp 00033 * updated for gps4palm V0.9.5 beta 00033 * 00034 * Revision 1.10.2.1 2007-10-05 22:06:17 mp 00035 * added Frank's changes (NOPROGRESSBAR) 00036 * 00037 * $Author: mp $ 00038 * 00039 * $Date: 2007-10-08 20:40:33 $ 00040 * 00041 * $Revision: 1.7.2.1 $ 00042 * 00043 * $Log: gifread_8c-source.html,v $ 00043 * Revision 1.7.2.1 2007-10-08 20:40:33 mp 00043 * updated for gps4palm V0.9.5 beta 00043 * 00044 * Revision 1.10.2.1 2007-10-05 22:06:17 mp 00045 * added Frank's changes (NOPROGRESSBAR) 00046 * 00047 * Revision 1.11 2007/07/11 16:00:00 fs 00048 * added ifndef NOPROGRESSBAR for testing 00049 * 00050 * Revision 1.10 2005/05/15 10:46:02 mp 00051 * added passing of file descriptor (fd) to functions 00052 * 00053 * Revision 1.9 2005/05/14 12:28:09 mp 00054 * added parameter fd to fread() 00055 * 00056 * Revision 1.8 2005/05/13 18:29:40 mp 00057 * modified decoding abortion 00058 * 00059 * Revision 1.7 2004/11/27 10:16:26 mp 00060 * replaced ErrFatalDisplay() by Die() for memory allocation failures 00061 * 00062 * Revision 1.6 2004/11/24 21:07:25 mp 00063 * moved static function declarations from header to implementation file 00064 * 00065 * Revision 1.5 2004/11/23 17:45:36 mp 00066 * moved unused variable to debug specific code block 00067 * 00068 * Revision 1.4 2004/03/10 17:18:39 mp 00069 * added progressbar.h 00070 * 00071 * Revision 1.3 2003/12/27 12:08:42 mp 00072 * repeated calling of cleanGIF() now handled properly 00073 * 00074 * Revision 1.2 2003/10/18 16:11:51 mp 00075 * renamed ImgInfo to gPrefs 00076 * 00077 * Revision 1.1.1.1 2003/07/14 18:59:29 mp 00078 * Imported GPS4Palm to CVS revision control. 00079 * 00080 * 00081 ****************************************************************************/ 00082 #include <PalmOS.h> 00083 #include <PalmCompatibility.h> 00084 #include "stringil.h" 00085 #include "gifread.h" 00086 #include "file_io.h" /* fread() */ 00087 #include "common.h" 00088 #include "Utils.h" /* Die() */ 00089 #ifndef NOPROGRESSBAR 00090 #include "progressbar.h" 00091 #endif 00092 00093 #define malloc MemPtrNew 00094 #define free MemPtrFree 00095 00096 extern PrefsType gPrefs; 00097 00098 Boolean color; 00099 unsigned short w,h,bandh; 00100 unsigned int mapmax; 00101 RGBColorType map[256]; 00102 00103 unsigned char tcmap[256]; 00104 00105 DmOpenRef scratch; 00106 char **lines, *lcur, *editln; 00107 00108 /***************************************************************************/ 00109 00110 extern short int *lwzstack, lwzsp, *table; 00111 00112 int nextLWZ(FileDescrType fd); 00113 void initLWZ(short int input_code_size); 00114 #define readLWZ(fd) (lwzsp ? lwzstack[--lwzsp] : nextLWZ(fd)) 00115 00116 #define USAT(a,b) (((b)<<8)|(a)) 00117 00118 int ycnt; 00119 00120 00121 /* Static Functions */ 00122 static void putline(FileDescrType fd, int ypos) GIFREAD_SECTION; 00123 static Boolean stop(void) GIFREAD_SECTION; 00124 00125 00126 static void putline(FileDescrType fd, int ypos) 00127 { 00128 unsigned char *cp; 00129 int xpos; 00130 00131 00132 #ifdef VERBOSE 00133 { 00134 char buf[10]; 00135 00136 StrIToA(buf,ycnt); 00137 strcat(buf," "); 00138 WinDrawChars(buf,strlen(buf),0,40); 00139 } 00140 #endif 00141 00142 #ifndef NOPROGRESSBAR 00143 progressbar(80 /* ypos */, ycnt++ /* val */, h /* total */); 00144 #endif 00145 00146 cp = editln; 00147 xpos = w; 00148 while( xpos-- ) 00149 *cp++ = tcmap[readLWZ(fd)]; 00150 DmWrite(lines[ypos / bandh], w * (ypos % bandh), editln, w); 00151 } 00152 00153 static Boolean stop(void) 00154 { 00155 EventType event; 00156 00157 EvtGetEvent(&event, 0); 00158 if (event.eType == penDownEvent && event.screenY < 160) { 00159 MemPtrFree(table); 00160 MemPtrFree(lwzstack); 00161 return 1; 00162 } else { 00163 return 0; 00164 } 00165 } 00166 00167 /***************************************************************************/ 00168 00169 int doGIF(FileDescrType fd) 00170 { 00171 unsigned char gbuf[24], c, *cp; 00172 int i, ypos, lace; 00173 int Bkgnd; 00174 LocalID lid; 00175 unsigned short dbrec; 00176 VoidHand hand; 00177 unsigned char cmap[3 * 256]; 00178 00179 lines = NULL; 00180 editln = NULL; 00181 scratch = 0; 00182 00183 fread(fd, gbuf, 13); 00184 00185 if (!strncmp(gbuf, "GIF87a", 6)) { 00186 strcpy(gPrefs.imgtype, "GIF87a"); 00187 } else if (!strncmp(gbuf, "GIF89a", 6)) { 00188 strcpy(gPrefs.imgtype, "GIF89a"); 00189 } else { 00190 return 1; 00191 } 00192 00193 00194 // w = USAT(gbuf[6], gbuf[7]); 00195 // h = USAT(gbuf[8], gbuf[9]); 00196 // [12] is aspect ratio 00197 mapmax = 2 << (gbuf[10] & 0x07); 00198 00199 if (gbuf[10] & 0x80) { /* Global CMap */ 00200 fread(fd, cmap, mapmax * 3); 00201 Bkgnd = gbuf[11]; 00202 } else { 00203 /* if no color maps are present default should have black and white as the first two colors. */ 00204 static int colors[] = { 0, 7, 1, 2, 4, 3, 5, 6 }; 00205 for (i = 0; i < 256 - 8; i++) { 00206 cmap[i * 3] = (colors[i & 7] & 1) ? ((255 - i) & 0xf8) : 0; 00207 cmap[i * 3 + 1] = (colors[i & 7] & 2) ? ((255 - i) & 0xf8) : 0; 00208 cmap[i * 3 + 2] = (colors[i & 7] & 4) ? ((255 - i) & 0xf8) : 0; 00209 } 00210 for (; i < 256; i++) { 00211 cmap[i * 3] = (colors[i & 7] & 1) ? 4 : 0; 00212 cmap[i * 3 + 1] = (colors[i & 7] & 2) ? 4 : 0; 00213 cmap[i * 3 + 2] = (colors[i & 7] & 4) ? 4 : 0; 00214 } 00215 Bkgnd = -1; /* background unspecified */ 00216 } 00217 00218 /* skip optional extension blocks (GIF89a) */ 00219 while (true) { 00220 if (fread(fd, gbuf, 1) == 0) { 00221 /* error: end of file */ 00222 return 2; 00223 } 00224 if (gbuf[0] == ',') { 00225 /* Image Separator found */ 00226 break; 00227 } else if (gbuf[0] == '!') { 00228 /* Extension Introducer found */ 00229 fread(fd, gbuf, 1); 00230 if (gbuf[0] == 0xFE) { 00231 /* Plain Text Extension */ 00232 /* read until Block Terminator found */ 00233 do { 00234 fread(fd, gbuf, 1); 00235 } while (gbuf[0] != '\0'); 00236 } else { 00237 /* any other extension, next byte: Block Size */ 00238 fread(fd, gbuf, 1); 00239 for (i = gbuf[0] + 1; i > 0; i--) { 00240 /* read complete block and Block Terminator */ 00241 fread(fd, gbuf, 1); 00242 } 00243 } 00244 } else { 00245 /* Invalid Data */ 00246 return 2; 00247 } 00248 } 00249 00250 /* read remaining bytes of Image Descriptor */ 00251 fread(fd, &gbuf[1], 9); 00252 00253 w = USAT(gbuf[5], gbuf[6]); 00254 h = USAT(gbuf[7], gbuf[8]); 00255 lace = gbuf[9] & 0x40; 00256 if (gbuf[9] & 0x80) { 00257 mapmax = 1 << ((gbuf[9] & 0x07) + 1); 00258 fread(fd, cmap, mapmax * 3); 00259 } 00260 00261 for( i = 0,cp = cmap; i < mapmax; i++ ) { 00262 map[i].r = *cp++; 00263 map[i].g = *cp++; 00264 map[i].b = *cp++; 00265 map[i].index = i; 00266 if( !color ) 00267 tcmap[i] = (map[i].r * 54 + map[i].g * 183 + map[i].b * 18) >> 8; 00268 else 00269 tcmap[i] = i; 00270 } 00271 00272 { 00273 char buf[40]; 00274 00275 StrPrintF(buf, "%d x %d", w, h); 00276 WinDrawChars(buf,strlen(buf),0 ,24); 00277 } 00278 00279 lwzstack = MemPtrNew(8192); 00280 table = MemPtrNew(16384); 00281 if (!lwzstack || !table ) 00282 Die("Out of Memory (gifread1)!"); 00283 00284 fread(fd, &c, 1); 00285 initLWZ(c); 00286 00287 lid = DmFindDatabase(0, "ZBOXZSCRATCHPAD"); 00288 if (!lid) { 00289 DmCreateDatabase(0, "ZBOXZSCRATCHPAD", 'BOXR', 'DATA', false); 00290 lid = DmFindDatabase(0, "ZBOXZSCRATCHPAD"); 00291 } 00292 scratch = DmOpenDatabase(0, lid, dmModeReadWrite); 00293 if (!scratch) 00294 ErrDisplay("Could not access scratchpad"); 00295 00296 while (DmNumRecords(scratch)) 00297 DmRemoveRecord(scratch, 0); 00298 00299 editln = malloc(w); 00300 bandh = 49152 / w; 00301 lines = malloc((h + bandh - 1) / bandh * 4); 00302 00303 for (i = 0; i < h; i += bandh) { 00304 dbrec = 65535; 00305 hand = DmNewRecord(scratch, &dbrec, w * bandh); 00306 if (!hand) 00307 Die("Out of Memory (gifread2)!"); 00308 lines[i / bandh] = MemHandleLock(hand); 00309 } 00310 00311 ycnt = 0; 00312 00313 if (lace) { 00314 for (ypos = 0; ypos < h; ypos += 8) { 00315 putline(fd, ypos); 00316 if ( stop() ) return 1; 00317 } 00318 for (ypos = 4; ypos < h; ypos += 8) { 00319 putline(fd, ypos); 00320 if ( stop() ) return 1; 00321 } 00322 for (ypos = 2; ypos < h; ypos += 4) { 00323 putline(fd, ypos); 00324 if ( stop() ) return 1; 00325 } 00326 for (ypos = 1; ypos < h; ypos += 2) { 00327 putline(fd, ypos); 00328 if ( stop() ) return 1; 00329 } 00330 } else { 00331 for (ypos = 0; ypos < h; ypos++) { 00332 putline(fd, ypos); 00333 if ( stop() ) return 1; 00334 } 00335 } 00336 00337 MemPtrFree(table); 00338 MemPtrFree(lwzstack); 00339 00340 return 0; 00341 } 00342 00343 /**************************************************/ 00344 void cleanGIF() 00345 { 00346 int i; 00347 00348 if (lines) { 00349 for (i = 0; i < h; i += bandh) 00350 MemPtrUnlock(lines[i / bandh]); 00351 } 00352 00353 if (scratch) { 00354 while (DmNumRecords(scratch)) 00355 DmRemoveRecord(scratch, 0); 00356 DmCloseDatabase(scratch); 00357 scratch = 0; 00358 } 00359 00360 if (lines) { 00361 free(lines); 00362 lines = 0; 00363 } 00364 00365 if (editln) { 00366 free(editln); 00367 editln = 0; 00368 } 00369 }