#include "xbcomm.h" static VOIDPARM flipl( p ) byte *p; { byte t; t = p[ 0 ]; p[ 0 ] = p[ 3 ]; p[ 3 ] = t; t = p[ 1 ]; p[ 1 ] = p[ 2 ]; p[ 2 ] = t; } static int getbyte( fp ) FILE *fp; { return( (int)getc( fp ) ); } static u_int getword( fp ) FILE *fp; { byte b1 = (byte)getc( fp ); byte b2 = (byte)getc( fp ); return( (u_int)(b1 + b2 * 256) ); } static u_int getbeword( fp ) FILE *fp; { byte b1 = (byte)getc( fp ); byte b2 = (byte)getc( fp ); return( (u_int)(b2 + b1 * 256) ); } static int getint( fp, gotGarbage ) FILE *fp; boolean *gotGarbage; { int c, i; boolean notDone; /* skip forward to start of next number */ c = getc( fp ); notDone = TRUE; *gotGarbage = FALSE; while ( notDone ) { /* eat comments */ if ( c IS POUNDSIGN ) /* if we're at a comment, read to end of line */ while ( c ISNT EOL AND c ISNT EOF) c = getc( fp ); if ( c IS EOF ) return( 0 ); if ( c >= ZERO AND c <= NINE ) /* we've found what we were looking for */ notDone = FALSE; else if ( NOT ( ( c IS SPACE ) OR ( c IS TAB ) OR ( c IS CR ) OR ( c IS EOL ) OR ( c IS COMMA ) ) ) /* see if we are getting garbage (non-whitespace) */ *gotGarbage = TRUE; if ( notDone ) c = getc( fp ); } /* we're at the start of a number, continue until we hit a non-number */ i = 0; notDone = TRUE; while ( notDone ) { i = ( i * 10 ) + ( c - ZERO ); c = getc( fp ); if ( c IS EOF ) return( i ); if ( ( c < ZERO ) OR ( c > NINE ) ) notDone = FALSE; } return( i ); } typedef struct { char type[ 6 ]; unsigned short width, height; char planes; } GIF_INFO; static char *getGIFInfo( VOIDPARM ) { FILE *fp; GIF_INFO gi; boolean swapEm=FALSE; int cCnt; char c, *d; char resStr[ 32 ], tempStr[ 32 ]; union { unsigned short theShort; char theChars[ 2 ]; } byteOrder; byteOrder.theShort = ( 'A' SHL_ 8 ) + 'B'; if ( byteOrder.theChars[ 0 ] IS 'A' ) swapEm = TRUE; fp = fopen( theFile, "r" ); fread( (char *) &gi, sizeof( GIF_INFO ), 1, fp ); gi.type[ 5 ] = NULLTERM; if ( swapEm ) { d = (char *) &(gi.width); c = d[ 1 ]; d[ 1 ] = d[ 0 ]; d[ 0 ] = c; d = (char *) &(gi.height); c = d[ 1 ]; d[ 1 ] = d[ 0 ]; d[ 0 ] = c; } gi.planes = ( gi.planes AND_ 0x07 ); sprintf( resStr, "[%dx%dx%dp]", gi.width, gi.height, gi.planes + 1 ); picRes = copyString( resStr ); sprintf( tempStr, "GIF {%s}", gi.type ); fclose( fp ); return( copyString( tempStr ) ); } /* > Scan through and look for 0xff followed by either 0xc0, 0xc1 or 0xc9. > Once you find those, skip a couple bytes and you can then pick up > the precision, height, width and number of components as 1 byte, > 2 byte, 2 byte and 1 byte integers respectively and in that order > (the 2 byte guys are in big endian order). > > The number of components roughly indiciates colour or grayscale (3 or 1). > The precision is how big each component is (almost always 8 bits). > Most files will have three, 8 bit components. */ static char *getJFIFInfo( VOIDPARM ) { FILE *fp; int oneByte; boolean gotMarker; int prec, comp, width, height; char resStr[ 32 ], tempStr[ 32 ]; fp = fopen( theFile, "r" ); oneByte = getbyte( fp ); while ( oneByte ISNT EOF ) { if ( (u_int)oneByte IS 0xff ) { oneByte = (u_int)getbyte( fp ); if ( ( oneByte IS 0xc0 ) OR ( oneByte IS 0xc1 ) OR ( oneByte IS 0xc9 ) ) { /* ...ignore one word... */ height = getword( fp ); /* Next byte should be precision... */ prec = (u_int)getbyte( fp ); /* Next two bytes should be height... */ height = getbeword( fp ); /* Next two bytes should be width... */ width = getbeword( fp ); /* Next byte should be number of components... */ comp = (u_int)getbyte( fp ); sprintf( resStr, "[%dx%dx%dp]", width, height, ( comp * prec ) ); break; } else if ( (u_int)oneByte ISNT 0xff ) oneByte = getbyte( fp ); } else oneByte = getbyte( fp ); } fclose( fp ); picRes = copyString( resStr ); sprintf( tempStr, "JPEG/JFIF" ); return( copyString( tempStr ) ); } typedef struct { int id; /* Magic number for pm format files. */ int np; /* Number of planes. Normally 1. */ int nrow; /* Number of rows. 1 - MAXNELM. */ int ncol; /* Number of columns. 1 - MAXNELM. */ int nband; /* Number of bands. */ int form; /* Pixel format. */ } PM_INFO; #define PM_MAGICNO 0x56494557 /* Hex for VIEW */ #define PM_A 0x8000 #define PM_C 0x8001 #define PM_S 0x8002 #define PM_I 0x8004 #define PM_F 0xc004 static char *getPMInfo( VOIDPARM ) { FILE *fp; PM_INFO pi; boolean flipit; char picType[ 5 ], resStr[ 32 ], tempStr[ 32 ]; fp = fopen( theFile, "r" ); flipit = FALSE; fread( (char *) &pi, sizeof( PM_INFO ), 1, fp ); fclose( fp ); if ( pi.id ISNT PM_MAGICNO ) { flipl( (byte *) &pi.id ); if ( pi.id IS PM_MAGICNO ) flipit = TRUE; else flipl( (byte *) &pi.id ); } if ( pi.id ISNT PM_MAGICNO ) return( "INVALID PM FILE!" ); if ( flipit ) { flipl( (byte *) &pi.np ); flipl( (byte *) &pi.nrow ); flipl( (byte *) &pi.ncol ); flipl( (byte *) &pi.nband ); flipl( (byte *) &pi.form ); } if ( pi.form IS PM_A ) sprintf( picType, "PM_A" ); else if ( pi.form IS PM_C ) sprintf( picType, "PM_C" ); else if ( pi.form IS PM_S ) sprintf( picType, "PM_S" ); else if ( pi.form IS PM_I ) sprintf( picType, "PM_I" ); else if ( pi.form IS PM_F ) sprintf( picType, "PM_F" ); sprintf( resStr, "[%dx%dx%dp]", pi.ncol, pi.nrow, pi.np ); picRes = copyString( resStr ); sprintf( tempStr, "PM {%s}", picType ); return( copyString( tempStr ) ); } static char *getPBMInfo( VOIDPARM ) { FILE *fp; /* char planes; */ char resStr[ 32 ], tempStr[ 32 ]; boolean garbage, intGarbage; int c, c1; int numBits, index; int w, h, maxv, planes; garbage = FALSE; maxv = 0; /* open the stream, if necesary */ fp = fopen( theFile, "r" ); /* read the first two bytes of the file to determine which format */ /* this file is. "P1" = ascii bitmap, "P2" = ascii greymap, */ /* "P3" = ascii pixmap, "P4" = raw bitmap, "P5" = raw greymap, */ /* "P6" = raw pixmap */ c = getc( fp ); c1 = getc( fp ); if ( ( c ISNT 'P' ) OR ( c1 < ONE ) OR ( c1 > SIX ) ) sprintf( tempStr, "CORRUPT PBM FILE!" ); else { /* read in header information */ w = getint( fp, &intGarbage ); garbage = ( garbage OR intGarbage ); h = getint( fp, &intGarbage ); garbage = ( garbage OR intGarbage ); /* if we're not reading a bitmap, read the 'max value' */ if ( NOT ( ( c1 IS ONE ) OR ( c1 IS FOUR ) ) ) { maxv = getint( fp, &intGarbage ); garbage = ( garbage OR intGarbage ); if ( maxv < 1 ) garbage = TRUE; /* to avoid 'div by zero' probs */ } if ( garbage ) sprintf( tempStr, "CORRUPT PBM FILE!" ); else { /* planes = ( ( maxv AND_ 0xfff0 ) SHR_ 4 ) + 1; */ numBits = 4 * sizeof( int ); planes = 1; for ( index = 1; index <= numBits; index++ ) if ( ( maxv SHR_ index ) AND_ 0x0001 ) /* bit #index is used */ planes = index + 1; sprintf( resStr, "[%dx%dx%dp]", w, h, planes ); picRes = copyString( resStr ); if ( c1 IS ONE ) sprintf( tempStr, "ASCII PBM" ); if ( c1 IS TWO ) sprintf( tempStr, "ASCII PGM" ); if ( c1 IS THREE ) sprintf( tempStr, "ASCII PPM" ); if ( c1 IS FOUR ) sprintf( tempStr, "RAW PBM" ); if ( c1 IS FIVE ) sprintf( tempStr, "RAW PGM" ); if ( c1 IS SIX ) sprintf( tempStr, "RAW PPM" ); } } fclose( fp ); return( copyString( tempStr ) ); } static char *getXBMInfo( VOIDPARM ) { FILE *fp; boolean notDone, gotWidth; int w, h; char line[ 256 ], resStr[ 32 ], tempStr[ 32 ]; fp = fopen( theFile, "r" ); gotWidth = FALSE; /* read width: skip lines until we hit a #define */ notDone = TRUE; while ( notDone ) { if ( NOT fgets( line, 256, fp ) ) { sprintf( tempStr, "CORRUPT XBM FILE!" ); notDone = FALSE; } else if ( strncmp( line, "#define", 7 ) IS 0 ) { if ( sscanf( line, "#define %*s %d", &w ) ISNT 1 ) sprintf( tempStr, "CORRUPT XBM FILE!" ); else gotWidth = TRUE; notDone = FALSE; } } /* read height: skip lines until we hit another #define */ notDone = gotWidth; while ( notDone ) { if ( NOT fgets( line, 256, fp ) ) { sprintf( tempStr, "CORRUPT XBM FILE!" ); notDone = FALSE; } else if ( strncmp( line, "#define", 7 ) IS 0 ) { if ( sscanf( line, "#define %*s %d", &h ) ISNT 1 ) sprintf( tempStr, "CORRUPT XBM FILE!" ); else { sprintf( resStr, "[%dx%dx1p]", w, h ); picRes = copyString( resStr ); sprintf( tempStr, "XBM" ); } notDone = FALSE; } } fclose( fp ); return( copyString( tempStr ) ); } static char *getPICInfo( VOIDPARM ) { FILE *fp; int magic, ignored; byte bpp; int w, h; char planes; char resStr[ 32 ], tempStr[ 32 ]; fp = fopen( theFile, "r" ); magic = getword( fp ); if (magic != 0x1234) { w = getword( fp ); h = getword( fp ); planes = 1; } else { w = getword( fp ); h = getword( fp ); ignored = getword( fp ); ignored = getword( fp ); bpp = (u_int)getbyte( fp ); planes = ( ( bpp AND_ 0xf0 ) SHR_ 4 ) + 1; } fclose( fp ); sprintf( resStr, "[%dx%dx%dp]", w, h, planes ); picRes = copyString( resStr ); sprintf( tempStr, "PIC" ); return( copyString( tempStr ) ); } VOIDPARM getFileStats( VOIDPARM ) { FILE *fp; char magicno[ 8 ]; /* first 8 bytes of file */ char *infoStr; fileType = UNKNOWN; /* try to determine what type of file we've got by reading the */ /* first couple bytes and looking for a Magic Number */ fp = fopen( theFile, "r" ); if ( fp IS NULL ) { if ( verboseOutput ) printf( "Can't open %s to determine file type!\n", theFile ); fileStats = copyString( "UNIDENTIFYABLE" ); return; } if ( verboseOutput ) { printf( "...determining type/gathering statistics for %s...", theFile ); fflush( stdout ); } fread( magicno, 8, 1, fp ); fclose( fp ); if ( strncmp( magicno, "GIF", 3 ) IS 0 ) { fileType = GIF; fileStats = getGIFInfo(); } else if ( strncmp( magicno, "hsi1", 4 ) IS 0 ) { fileType = JFIF; fileStats = copyString ( "HSI proprietary JPEG" ); picRes = copyString( "[unknown resolution]" ); } else if ( magicno[ 0 ] IS (char) -1 AND magicno[ 1 ] IS (char) -40 AND magicno[ 2 ] IS (char) -1 ) { fileType = JFIF; fileStats = getJFIFInfo(); } else if ( strncmp( magicno, "VIEW", 4) IS 0 OR strncmp( magicno, "WEIV", 4) IS 0 ) { fileType = PM; fileStats = getPMInfo(); } else if ( magicno[ 0 ] IS 'P' AND magicno[ 1 ] >= '1' AND magicno[ 1 ] <= '6') { fileType = PBM; fileStats = getPBMInfo(); } else if ( strncmp( magicno, "#define", 7 ) IS 0 ) { fileType = XBM; fileStats = getXBMInfo(); } else if ( ( (u_int) magicno[ 0 ] IS 0x34 ) AND ( (u_int) magicno[ 1 ] IS 0x12 ) ) { fileType = PIC; fileStats = getPICInfo(); } else fileStats = copyString( "UNKNOWN" ); if ( DEBUG_PROC ) printf( "File %s is of type %s...\n", theFile, fileStats ); if ( verboseOutput ) printf( "done.\n" ); }