00001 /***************************************************************************** 00002 * 00003 * $RCSfile: pngdec_8c-source.html,v $ 00004 * 00005 * PNG Image Decoder 00006 * 00007 * created: 2002-12-15 00008 * 00009 * History: 00010 * 2002-12-15: imported from the program PiNGer which is 00011 * part of the ZBoxZ application suite (Rev. 0.30) 00012 * by Tom Zerucha. 00013 * 2002-12-30: added progress bar, modified status messages, 00014 * fixed cleanPNG() to work when called after early abort 00015 * 00016 * This program is Copyright (C) 12/2002 Matthias Prinke 00017 * <matthias.prinke@surfeu.de> and covered by GNU's GPL. 00018 * In particular, this program is free software and comes WITHOUT 00019 * ANY WARRANTY. 00020 * 00021 * $Author: mp $ 00022 * 00023 * $Date: 2007-10-08 20:40:34 $ 00024 * 00025 * $Revision: 1.7.2.1 $ 00026 * 00027 * $Log: pngdec_8c-source.html,v $ 00027 * Revision 1.7.2.1 2007-10-08 20:40:34 mp 00027 * updated for gps4palm V0.9.5 beta 00027 * 00028 * Revision 1.9 2005-05-15 10:41:02 mp 00029 * added parameter fd to most functions 00030 * 00031 * Revision 1.8 2005/05/14 12:27:14 mp 00032 * added parameter fd to fclose(), fread(), and feof() 00033 * 00034 * Revision 1.7 2005/05/13 18:29:26 mp 00035 * modified decoding abortion 00036 * 00037 * Revision 1.6 2004/11/27 10:16:26 mp 00038 * replaced ErrFatalDisplay() by Die() for memory allocation failures 00039 * 00040 * Revision 1.5 2004/11/24 21:20:02 mp 00041 * moved static function declarations from header to implementation file 00042 * 00043 * Revision 1.4 2004/03/10 17:18:24 mp 00044 * added progressbar.h 00045 * 00046 * Revision 1.3 2003/12/27 12:09:19 mp 00047 * repeated calling og cleanPNG() now handled properly 00048 * 00049 * Revision 1.2 2003/10/18 16:11:51 mp 00050 * renamed ImgInfo to gPrefs 00051 * 00052 * Revision 1.1.1.1 2003/07/14 18:59:29 mp 00053 * Imported GPS4Palm to CVS revision control. 00054 * 00055 * 00056 ****************************************************************************/ 00057 #include <PalmOS.h> 00058 #include <Unix/sys_types.h> 00059 #include "stringil.h" 00060 #include "common.h" 00061 #include "pngdec.h" 00062 #include "SysZLib.h" 00063 #include "file_io.h" /* fread(), feof(), fclose */ 00064 #include "Utils.h" /* Die() */ 00065 #include "progressbar.h" 00066 00067 #define QUIET 00068 00069 extern PrefsType gPrefs; 00070 00071 /* Mark's macros to extract big-endian short and long ints: */ 00072 typedef unsigned char uch; 00073 typedef unsigned short ush; 00074 typedef unsigned long ulg; 00075 #define SH(p) ((ush)(uch)((p)[1]) | ((ush)(uch)((p)[0]) << 8)) 00076 #define LG(p) ((ulg)(SH((p)+2)) | ((ulg)(SH(p)) << 16)) 00077 00078 #define BS 1440 00079 #define OBS (3*BS) 00080 unsigned char buffer[BS]; 00081 static uch outbuf[OBS]; 00082 00083 extern Boolean color; 00084 00085 unsigned short int w, h; 00086 unsigned short int bitdisp, bdepth, ityp, lace, nplte = 0, gskip = 00087 1, bskip, bandh; 00088 00089 static long sz; 00090 00091 int trspflg = 0; 00092 00093 static unsigned short int bkgdr = 0x80; 00094 static unsigned short int bkgdg = 0x80; 00095 static unsigned short int bkgdb = 0x80; 00096 00097 static unsigned short int tspr = 0; 00098 static unsigned short int tspg = 0; 00099 static unsigned short int tspb = 0; 00100 00101 static unsigned short int bkgdy = 0x80; 00102 static unsigned short int tspy = 0; 00103 00104 LocalID lid; 00105 DmOpenRef scratch; 00106 00107 char **lines, *lcur, *editln; 00108 00109 unsigned char cmap[256], r[256], g[256], b[256], a[256]; 00110 unsigned int mapmax = 0; 00111 RGBColorType map[256]; 00112 00113 00114 /* Static Functions */ 00115 static void filter(unsigned char *curr, unsigned char *prev, 00116 int filter, int bpp, int llen) PNGDEC_SECTION; 00117 static int getcmap(unsigned int r, unsigned int g, 00118 unsigned int b, unsigned int a) PNGDEC_SECTION; 00119 static int doidat(FileDescrType fd) PNGDEC_SECTION; 00120 static void doihdr(FileDescrType fd) PNGDEC_SECTION; 00121 static void doprefix(FileDescrType fd) PNGDEC_SECTION; 00122 00123 00124 /**************************************************/ 00125 static 00126 void filter(unsigned char *curr, unsigned char *prev, int filter, 00127 int bpp, int llen) 00128 { 00129 unsigned char *curr0 = curr, *prev0, *zp = NULL; 00130 int a, b, c, pa, pb, pc; 00131 00132 if (filter > 1 && !prev) { 00133 zp = malloc(llen); 00134 bzero(zp, llen); 00135 prev = zp; 00136 } 00137 00138 switch (filter) { 00139 00140 case 1: 00141 curr += bpp; 00142 llen -= bpp; 00143 prev = curr0; 00144 case 2: 00145 while (llen--) 00146 *curr++ += *prev++; 00147 case 0: 00148 break; 00149 00150 case 3: 00151 while (bpp-- && llen--) 00152 *curr++ += *prev++ >> 1; 00153 while (llen--) 00154 *curr++ += (*prev++ + *curr0++) >> 1; 00155 break; 00156 00157 case 4: 00158 prev0 = prev; 00159 while (bpp-- && llen--) 00160 *curr++ += *prev++; 00161 while (llen--) { 00162 a = *curr0++, b = *prev++, c = *prev0++; 00163 00164 pa = abs(b - c); 00165 pb = abs(a - c); 00166 pc = abs(a + b - (c << 1)); 00167 00168 *curr++ += (pa <= pb && pa <= pc) ? a : (pb <= pc) ? b : c; 00169 } 00170 break; 00171 } 00172 if (zp) 00173 free(zp); 00174 } 00175 00176 /* for color to grey (of 65536): R=13926 - 54, G=46884 - 183, B=4725 - 18 */ 00177 /**************************************************/ 00178 /* these are unsigned ints, but are actually 8 bit values */ 00179 static 00180 int getcmap(unsigned int r, unsigned int g, unsigned int b, unsigned int a) 00181 { 00182 00183 /* a is transparency and is not used yet, or if == 0xff has no effect */ 00184 if( trspflg ) { 00185 if (!a || (a == 255 && ityp == 2 && r == tspr && g == tspg && b == tspb)) { 00186 r = bkgdr; 00187 g = bkgdg; 00188 b = bkgdb; 00189 } else if (a < 255) { 00190 r = (bkgdr * (255 - a) + r * a) >> 8; /* should really be /255 */ 00191 g = (bkgdg * (255 - a) + g * a) >> 8; 00192 b = (bkgdb * (255 - a) + b * a) >> 8; 00193 } 00194 } 00195 00196 if (color) { 00197 map[mapmax].r = r; 00198 map[mapmax].g = g; 00199 map[mapmax].b = b; 00200 map[mapmax].index = mapmax; 00201 return mapmax++; 00202 } else 00203 return (r * 54 + g * 183 + b * 18) >> 8; 00204 } 00205 00206 /**************************************************/ 00207 static 00208 int doidat(FileDescrType fd) 00209 { 00210 /* static */ 00211 unsigned char *p; /* always points to next filter byte */ 00212 int cur_x, cur_y, cur_pass, cur_xoff, cur_yoff, cur_xskip, cur_yskip, chunk = 00213 0; 00214 long cur_width, cur_linebytes; 00215 z_stream zstrm; 00216 Word dbrec; 00217 VoidHand hand; 00218 long i, j, k; 00219 unsigned char *eod; 00220 int err = Z_OK; 00221 00222 00223 j = (sz > BS) ? BS : sz; 00224 fread(fd, buffer, (size_t) j); 00225 sz -= j; 00226 00227 memset(&zstrm, 0, sizeof(zstrm)); 00228 zstrm.next_in = buffer; 00229 zstrm.avail_in = j; 00230 zstrm.next_out = p = outbuf; 00231 zstrm.avail_out = OBS; 00232 00233 inflateInit(&zstrm); 00234 00235 cur_y = 0; 00236 cur_pass = 1; /* interlace pass: 1 through 7 */ 00237 cur_xoff = cur_yoff = 0; 00238 cur_xskip = cur_yskip = lace ? 8 : 1; 00239 cur_width = (w + cur_xskip - 1) / cur_xskip; /* round up */ 00240 cur_linebytes = ((cur_width * bitdisp + 7) >> 3) + 1; /* round, fltr */ 00241 00242 lid = DmFindDatabase(0, "ZBOXZSCRATCHPAD"); 00243 if (!lid) { 00244 DmCreateDatabase(0, "ZBOXZSCRATCHPAD", 'BOXR', 'DATA', false); 00245 lid = DmFindDatabase(0, "ZBOXZSCRATCHPAD"); 00246 } 00247 scratch = DmOpenDatabase(0, lid, dmModeReadWrite); 00248 if (!scratch) 00249 ErrDisplay("Could not access scratchpad"); 00250 00251 editln = malloc(w+8); /* +8 for interleave overflow */ 00252 bandh = 49152 / w; 00253 lines = malloc((h + bandh - 1) / bandh * 4); 00254 00255 for (i = 0; i < h; i += bandh) { 00256 dbrec = 65535; 00257 hand = DmNewRecord(scratch, &dbrec, w * bandh); 00258 if (!hand) 00259 Die("Out of Memory (pngdec)!"); 00260 lines[i / bandh] = MemHandleLock(hand); 00261 } 00262 00263 for (i = 0; i < nplte; i++) 00264 cmap[i] = getcmap(r[i], g[i], b[i], a[i]); 00265 00266 k = (1 << bitdisp) - 1; 00267 while (err != Z_STREAM_END) { 00268 00269 err = inflate(&zstrm, Z_PARTIAL_FLUSH); 00270 eod = outbuf + OBS - zstrm.avail_out; 00271 00272 { 00273 EventType event; 00274 EvtGetEvent(&event, 0); 00275 if (event.eType == penDownEvent && event.screenY < 160) { 00276 inflateEnd(&zstrm); 00277 return 1; 00278 } 00279 } 00280 00281 while (p + cur_linebytes <= eod) { 00282 00283 if( p[0] ) 00284 filter(&p[1], cur_y ? &p[1 - cur_linebytes] : NULL, p[0], 00285 (bitdisp + 7) >> 3, cur_linebytes - 1); 00286 00287 cur_x = cur_xoff; 00288 lcur = lines[cur_y / bandh]; 00289 lcur += w * (cur_y % bandh); 00290 (void) memcpy(editln, lcur, w); 00291 00292 switch (ityp) { 00293 00294 case 2: 00295 if (bitdisp == 16) 00296 for (j = 1; j < cur_linebytes; j += gskip, cur_x += cur_xskip) 00297 editln[cur_x] = getcmap(p[j], p[j + 2], p[j + 4], 0xff); 00298 else 00299 for (j = 1; j < cur_linebytes; j += gskip, cur_x += cur_xskip) 00300 editln[cur_x] = getcmap(p[j], p[j + 1], p[j + 2], 0xff); 00301 break; 00302 case 6: 00303 if (bitdisp == 16) 00304 for (j = 1; j < cur_linebytes; j += gskip, cur_x += cur_xskip) 00305 editln[cur_x] = getcmap(p[j], p[j + 2], p[j + 4], p[j + 6]); 00306 else 00307 for (j = 1; j < cur_linebytes; j += gskip, cur_x += cur_xskip) 00308 editln[cur_x] = getcmap(p[j], p[j + 1], p[j + 2], p[j + 3]); 00309 break; 00310 00311 case 3: 00312 if (bitdisp == 8 && gskip == 1) { 00313 /* optimized copy colormap entry direct */ 00314 unsigned char *s = &p[1]; 00315 j = cur_linebytes - 1; 00316 if (color) 00317 while( j-- ) { 00318 editln[cur_x] = *s++; 00319 cur_x += cur_xskip; 00320 } 00321 else /* still need to go through cmap */ 00322 while( j-- ) { 00323 editln[cur_x] = cmap[*s++]; 00324 cur_x += cur_xskip; 00325 } 00326 } else 00327 for (j = 1; j < cur_linebytes; j += gskip, cur_x += cur_xskip) 00328 for (i = 8 - bskip; i >= 0; i -= bskip) 00329 editln[cur_x] = cmap[((p[j] >> i) & k) << (8 - bskip)]; 00330 break; 00331 case 0: 00332 case 4: /* if grey == trsp then sub bkgdy */ 00333 00334 if (bitdisp == 8 && gskip == 1) { 00335 /* optimized copy colormap entry direct */ 00336 unsigned char *s = &p[1]; 00337 j = cur_linebytes - 1; 00338 while( j-- ) { 00339 editln[cur_x] = *s++; 00340 cur_x += cur_xskip; 00341 } 00342 } 00343 else 00344 for (j = 1; j < cur_linebytes; j += gskip, cur_x += cur_xskip) 00345 for (i = 8 - bskip; i >= 0; i -= bskip) 00346 editln[cur_x] = ((p[j] >> i) & k) << (8 - bskip); 00347 break; 00348 } 00349 00350 DmWrite(lines[cur_y / bandh], w * (cur_y % bandh), editln, w); 00351 00352 p += cur_linebytes; 00353 cur_y += cur_yskip; 00354 00355 #ifndef QUIET 00356 { 00357 char buf[5]; 00358 StrIToA(buf, chunk); 00359 WinDrawChars(buf, strlen(buf), 25, 0); 00360 } 00361 #endif 00362 00363 progressbar(80 /* ypos */, chunk++ /* val */, h /* total */); 00364 00365 if (lace) { 00366 while (cur_y >= h) { /* may loop if very short image */ 00367 ++cur_pass; 00368 if (cur_pass & 1) { /* beginning an odd pass */ 00369 cur_yoff = cur_xoff; 00370 cur_xoff = 0; 00371 cur_xskip >>= 1; 00372 } else { /* beginning an even pass */ 00373 if (cur_pass == 2) 00374 cur_xoff = 4; 00375 else { 00376 cur_xoff = cur_yoff >> 1; 00377 cur_yskip >>= 1; 00378 } 00379 cur_yoff = 0; 00380 } 00381 cur_y = cur_yoff; 00382 /* effective width is reduced if even pass: subtract cur_xoff */ 00383 cur_width = (w - cur_xoff + cur_xskip - 1) / cur_xskip; 00384 cur_linebytes = ((cur_width * bitdisp + 7) >> 3) + 1; 00385 } 00386 } else if (cur_y >= h) { 00387 break; 00388 } 00389 } /*p<eod */ 00390 00391 if (err != Z_OK && err != Z_STREAM_END) { 00392 char buf[8]; 00393 StrIToA(buf, err); 00394 strcat(buf, " |"); 00395 WinDrawChars(buf, strlen(buf), 80, 0); 00396 inflateEnd(&zstrm); 00397 SysTaskDelay(300); 00398 return 1; 00399 } 00400 00401 if (err != Z_OK) 00402 break; 00403 00404 /* fix p leaving a history line */ 00405 i = eod - p + cur_linebytes; 00406 (void) memcpy(outbuf, p - cur_linebytes, i); 00407 zstrm.next_out = outbuf + i; 00408 zstrm.avail_out = OBS - i; 00409 p = outbuf + cur_linebytes; 00410 00411 if (zstrm.avail_in > BS / 2) 00412 continue; 00413 00414 (void) memcpy(buffer, zstrm.next_in, zstrm.avail_in); 00415 zstrm.next_in = buffer; 00416 00417 if (!sz) { 00418 char buf[12]; 00419 fread(fd, buf, 12); /*crc,siz,IDAT */ 00420 sz = LG(&buf[4]); 00421 #ifndef QUIET 00422 WinDrawChars(&buf[8], 4, 0, 0); 00423 #endif 00424 } 00425 00426 i = BS - zstrm.avail_in; 00427 j = (sz > i) ? i : sz; 00428 fread(fd, &buffer[zstrm.avail_in], j); 00429 00430 sz -= j; 00431 zstrm.avail_in += j; 00432 00433 } 00434 inflateEnd(&zstrm); 00435 /* fread(fd, buffer, 4); */ 00436 return 0; 00437 } 00438 00439 /**************************************************/ 00440 char *pngty[] = 00441 { "Gray", "Unk1", "RGB ", "CMAP", "GryA", "Unk5", "RGBA", "Unk7" }; 00442 00443 static 00444 void doihdr(FileDescrType fd) 00445 { 00446 int i; 00447 #ifndef QUIET 00448 char buf[20]; 00449 #endif 00450 /* search for IHDR */ 00451 while (!feof(fd)) { 00452 00453 if (8 != fread(fd, buffer, 8)) 00454 break; 00455 sz = LG(buffer); 00456 (void) memcpy(buffer, &buffer[4], 4); 00457 #ifndef QUIET 00458 WinDrawChars(buffer, 4, 0, 0); 00459 #endif 00460 buffer[4] = 0; 00461 00462 /*------* 00463 | IHDR | 00464 *------*/ 00465 if (strcmp(buffer, "IHDR") == 0) { 00466 00467 fread(fd, buffer, sz + 4); 00468 00469 w = LG(buffer); 00470 h = LG(buffer + 4); 00471 bitdisp = (unsigned char) buffer[8]; 00472 bdepth = bitdisp; 00473 ityp = (unsigned char) buffer[9]; 00474 lace = (unsigned char) buffer[12]; 00475 00476 StrPrintF(gPrefs.imgtype, "PNG Type%d (%s) %s", ityp, pngty[ityp], 00477 (lace) ? "Interlaced" : ""); 00478 00479 { 00480 Char buf[40]; 00481 00482 StrPrintF(buf, "%d x %d", w, h); 00483 WinDrawChars(buf, StrLen(buf), 0, 24); 00484 } 00485 00486 #ifndef QUIET 00487 WinDrawChars("Depth", 5, 1, 60); 00488 StrIToA(buf, bitdisp); 00489 WinDrawChars(buf, strlen(buf), 30, 60); 00490 00491 WinDrawChars("/", 2, 45, 0); 00492 00493 WinDrawChars("Type", 4, 1, 15); 00494 StrIToA(buf, ityp); 00495 WinDrawChars(buf, strlen(buf), 30, 15); 00496 WinDrawChars(pngty[ityp], 4, 40, 15); 00497 00498 if (lace) { 00499 WinDrawChars("Interlaced", 10, 0, 75); 00500 StrIToA(buf, h * 15 / 8); 00501 WinDrawChars(buf, strlen(buf), 50, 0); 00502 } else { 00503 StrIToA(buf, h); 00504 WinDrawChars(buf, strlen(buf), 50, 0); 00505 } 00506 #endif 00507 00508 switch (ityp) { 00509 case 0: 00510 if (bitdisp == 16) 00511 gskip = 2; 00512 for (i = 0; i < 256; i++) /* for the IIIc */ 00513 r[i] = g[i] = b[i] = i; 00514 memset(a, 0xff, 256); 00515 nplte = 256; 00516 break; 00517 case 2: 00518 if (bitdisp == 16) 00519 gskip = 6; 00520 else 00521 gskip = 3; 00522 bitdisp *= 3; /* RGB */ 00523 break; 00524 case 4: 00525 if (bitdisp == 16) 00526 gskip = 4; 00527 else 00528 gskip = 2; 00529 bitdisp *= 2; /* gray+alpha */ 00530 for (i = 0; i < 256; i++) /* for the IIIc */ 00531 r[i] = g[i] = b[i] = i; 00532 memset(a, 0xff, 256); 00533 nplte = 256; 00534 break; 00535 case 6: 00536 if (bitdisp == 16) 00537 gskip = 8; 00538 else 00539 gskip = 4; 00540 bitdisp *= 4; /* RGBA */ 00541 break; 00542 } 00543 bskip = bitdisp / gskip; 00544 break; 00545 00546 } else { 00547 /* BYPASS REST OF UNKNOWN RECORD */ 00548 i = 0; 00549 while (sz > i) { 00550 sz -= i; 00551 i = (sz > BS) ? BS : sz; 00552 fread(fd, buffer, i); 00553 } 00554 fread(fd, buffer, 4); /* crc */ 00555 } 00556 } 00557 } 00558 00559 /**************************************************/ 00560 static 00561 void doprefix(FileDescrType fd) 00562 { 00563 int i, j; 00564 unsigned char *c; 00565 00566 /* Look for IDAT and other used chunks */ 00567 while (!feof(fd)) { 00568 00569 if (8 != fread(fd, buffer, 8)) 00570 break; 00571 sz = LG(buffer); 00572 (void) memcpy(buffer, &buffer[4], 4); 00573 buffer[4] = 0; 00574 #ifndef QUIET 00575 WinDrawChars(buffer, 4, 0, 0); 00576 #endif 00577 c = buffer; 00578 00579 if (strcmp(buffer, "IDAT") == 0) 00580 break; 00581 00582 else if (strcmp(buffer, "PLTE") == 0) { 00583 fread(fd, buffer, sz + 4); 00584 nplte = sz / 3; 00585 00586 /* save palette and do later with alpha and bkgd */ 00587 for (i = j = 0; i < nplte; i++, j += 3) { 00588 r[i] = *c++; 00589 g[i] = *c++; 00590 b[i] = *c++; 00591 } 00592 memset(a, 0xff, nplte); 00593 } 00594 /* The next two must occur after PLTE */ 00595 else if (strcmp(buffer, "tRNS") == 0) { 00596 /* Swap bKGD gray for tRNS gray (if no other background) */ 00597 trspflg = 1; 00598 00599 fread(fd, buffer, sz + 4); 00600 switch (ityp) { 00601 case 0: 00602 tspy = SH(buffer); /* transparent gray value */ 00603 break; 00604 case 3: 00605 c = buffer; 00606 for (i = 0; i < sz; ++i) 00607 a[i] = *c++; 00608 break; 00609 case 2: /* RGB */ 00610 tspr = SH(c); 00611 c += 2; 00612 tspg = SH(c); 00613 c += 2; 00614 tspb = SH(c); 00615 if (bdepth == 16) { 00616 tspr >>= 8; 00617 tspg >>= 8; 00618 tspb >>= 8; 00619 } 00620 break; 00621 } 00622 00623 } else if (strcmp(buffer, "bKGD") == 0) { 00624 fread(fd, buffer, sz + 4); 00625 switch (ityp) { 00626 case 0: 00627 case 4: 00628 bkgdy = SH(c); 00629 if (bdepth == 16) 00630 bkgdy >>= 8; 00631 break; 00632 case 3: 00633 bkgdr = r[*c]; 00634 bkgdg = g[*c]; 00635 bkgdb = b[*c]; 00636 break; 00637 case 2: 00638 case 6: 00639 bkgdr = SH(c); 00640 c += 2; 00641 bkgdg = SH(c); 00642 c += 2; 00643 bkgdb = SH(c); 00644 if (bdepth == 16) { 00645 bkgdr >>= 8; 00646 bkgdg >>= 8; 00647 bkgdb >>= 8; 00648 } 00649 break; 00650 } 00651 } else if (strcmp(buffer, "IEND") == 0) { 00652 break; 00653 } else { 00654 /* BYPASS REST OF UNIMPLEMENTED RECORD */ 00655 i = 0; 00656 while (sz > i) { 00657 sz -= i; 00658 i = (sz > BS) ? BS : sz; 00659 fread(fd, buffer, i); 00660 } 00661 fread(fd, buffer, 4); /* crc */ 00662 } 00663 } 00664 } 00665 00666 /**************************************************/ 00667 void cleanPNG(void) 00668 { 00669 int i; 00670 00671 if (lines) { 00672 for (i = 0; i < h; i += bandh) 00673 MemPtrUnlock(lines[i / bandh]); 00674 } 00675 00676 if (scratch) { 00677 while (DmNumRecords(scratch)) 00678 DmRemoveRecord(scratch, 0); 00679 DmCloseDatabase(scratch); 00680 scratch = 0; 00681 } 00682 00683 if (lines) { 00684 free(lines); 00685 lines = 0; 00686 } 00687 00688 if (editln) { 00689 free(editln); 00690 editln = 0; 00691 } 00692 } 00693 00694 /**************************************************/ 00695 static unsigned char PNGmagic[] = "\211PNG\r\n\032\n"; 00696 00697 int doPNG(FileDescrType fd) 00698 { 00699 unsigned char magic[8]; 00700 int i; 00701 00702 lines = NULL; 00703 editln = NULL; 00704 scratch = 0; 00705 00706 fread(fd, magic, 8); 00707 if (memcmp(magic, PNGmagic, 8)) { 00708 fclose(fd); 00709 return 1; 00710 } 00711 00712 doihdr(fd); 00713 00714 for (i = 0; i < 256; i++) 00715 cmap[i] = i; 00716 00717 doprefix(fd); 00718 00719 if ((!nplte && ityp == 3) || strcmp(buffer, "IDAT")) { 00720 fclose(fd); 00721 return 1; 00722 } 00723 00724 ZLSetup; 00725 EvtResetAutoOffTimer(); 00726 i = doidat(fd); 00727 EvtResetAutoOffTimer(); 00728 ZLTeardown; 00729 fclose(fd); 00730 00731 if (i) { 00732 cleanPNG(); 00733 return 1; 00734 } 00735 return 0; 00736 }