GPS4Palm

Source Code Documentation


gifread.c

Go to the documentation of this file.
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 }

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