00001 /***************************************************************************** 00002 * 00003 * $RCSfile: imginfo_8c-source.html,v $ 00004 * 00005 * Image File Information Functions 00006 * 00007 * Note: For GIF, the code has been taken from gifread.c. 00008 * FOR PNG, the code has been taken from pngdec.c. 00009 * 00010 * This program is Copyright (C) 03/2005 Matthias Prinke 00011 * <matthias.prinke@surfeu.de> and covered by GNU's GPL. 00012 * In particular, this program is free software and comes WITHOUT 00013 * ANY WARRANTY. 00014 * 00015 * $Author: mp $ 00016 * 00017 * $Date: 2007-10-08 20:40:33 $ 00018 * 00019 * $Revision: 1.1.2.1 $ 00020 * 00021 * $Log: imginfo_8c-source.html,v $ 00021 * Revision 1.1.2.1 2007-10-08 20:40:33 mp 00021 * updated for gps4palm V0.9.5 beta 00021 * 00022 * Revision 1.1 2005-05-14 12:31:29 mp 00023 * initial version 00024 * 00025 * 00026 ****************************************************************************/ 00027 #include <PalmOS.h> 00028 #include "file_io.h" 00029 #include "imginfo.h" 00030 #include "stringil.h" 00031 00032 #define USAT(a,b) (((b)<<8)|(a)) 00033 #define BS 1440 00034 00035 /* Mark's macros to extract big-endian short and long ints: */ 00036 typedef unsigned char uch; 00037 typedef unsigned short ush; 00038 typedef unsigned long ulg; 00039 #define SH(p) ((ush)(uch)((p)[1]) | ((ush)(uch)((p)[0]) << 8)) 00040 #define LG(p) ((ulg)(SH((p)+2)) | ((ulg)(SH(p)) << 16)) 00041 00042 /* magic bytes to determine image type */ 00043 const char png_magic[] = "\211PNG\r\n\032\n"; 00044 const char gif87a_magic[] = "GIF87a"; 00045 const char gif89a_magic[] = "GIF89a"; 00046 const char jpeg_magic[] = "\xFF\xD8"; /* 0xFF 0xD8 (SOI - Start of Image) */ 00047 00048 00049 Boolean imginfo(FileDescrType fd, UInt8 *type, UInt16 *width, UInt16 *height) 00050 { 00051 unsigned char buf[24]; 00052 unsigned int mapmax; 00053 unsigned int i; 00054 long int sz; 00055 00056 fread(fd, buf, 8); 00057 00058 if (strncmp(buf, png_magic, strlen((char *)png_magic)) == 0) { 00059 /* file is a PNG */ 00060 *type = IMGTYPE_PNG; 00061 00062 /* search for IHDR */ 00063 while (!feof(fd)) { 00064 00065 if (8 != fread(fd, buf, 8)) 00066 break; 00067 sz = LG(buf); 00068 (void) memcpy(buf, &buf[4], 4); 00069 00070 buf[4] = 0; 00071 00072 /*------* 00073 | IHDR | 00074 *------*/ 00075 if (strcmp(buf, "IHDR") == 0) { 00076 00077 fread(fd, buf, sz + 4); 00078 00079 *width = LG(buf); 00080 *height = LG(buf + 4); 00081 rewind(fd); 00082 return false; 00083 00084 } else { 00085 /* BYPASS REST OF UNKNOWN RECORD */ 00086 i = 0; 00087 while (sz > i) { 00088 sz -= i; 00089 i = (sz > BS) ? BS : sz; 00090 fread(fd, buf, i); 00091 } 00092 fread(fd, buf, 4); /* crc */ 00093 } 00094 } /* while (!feof()) */ 00095 rewind(fd); 00096 return true; 00097 00098 } else if (strncmp(buf, gif87a_magic, strlen((char *)gif87a_magic)) == 0 || 00099 strncmp(buf, gif89a_magic, strlen((char *)gif89a_magic)) == 0) { 00100 rewind(fd); 00101 00102 /* file is a GIF */ 00103 *type = IMGTYPE_GIF; 00104 00105 fread(fd, buf, 13); 00106 00107 /* read past colormap */ 00108 mapmax = 2 << (buf[10] & 0x07); 00109 00110 if (buf[10] & 0x80) { 00111 /* Global CMap */ 00112 fseek(fd, mapmax * 3, SEEK_CUR); 00113 } 00114 00115 /* skip optional extension blocks (GIF89a) */ 00116 while (true) { 00117 if (fread(fd, buf, 1) == 0) { 00118 /* error: end of file */ 00119 rewind(fd); 00120 return true; 00121 } 00122 if (buf[0] == ',') { 00123 /* Image Separator found */ 00124 break; 00125 } else if (buf[0] == '!') { 00126 /* Extension Introducer found */ 00127 fread(fd, buf, 1); 00128 if (buf[0] == 0xFE) { 00129 /* Plain Text Extension */ 00130 /* read until Block Terminator found */ 00131 do { 00132 fread(fd, buf, 1); 00133 } while (buf[0] != '\0'); 00134 } else { 00135 /* any other extension, next byte: Block Size */ 00136 fread(fd, buf, 1); 00137 for (i = buf[0] + 1; i > 0; i--) { 00138 /* read complete block and Block Terminator */ 00139 fread(fd, buf, 1); 00140 } 00141 } 00142 } else { 00143 /* Invalid Data */ 00144 rewind(fd); 00145 return true; 00146 } 00147 } /* while (true) */ 00148 00149 /* read remaining bytes of Image Descriptor */ 00150 fread(fd, &buf[1], 9); 00151 00152 *width = USAT(buf[5], buf[6]); 00153 *height = USAT(buf[7], buf[8]); 00154 rewind(fd); 00155 return false; 00156 00157 } else if (strncmp(buf, jpeg_magic, strlen((char *)jpeg_magic)) == 0) { 00158 /* file is a JPEG */ 00159 *type = IMGTYPE_JPEG; 00160 00161 /* currently not supported */ 00162 *width = 0; 00163 *height = 0; 00164 rewind(fd); 00165 return false; 00166 00167 } else { 00168 /* file type is unknown */ 00169 *type = IMGTYPE_UNKNOWN; 00170 rewind(fd); 00171 return true; 00172 00173 } 00174 }