home *** CD-ROM | disk | FTP | other *** search
- /*
- ** Copyright (c) 1989, 1990
- ** Truevision, Inc.
- ** All Rights Reserverd
- **
- ** TGAPACK reads the contents of a Truevision(R) TGA(tm) File and provides
- ** the ability to compress the image data via run length encoding, or
- ** to uncompress images that have been stored in a run length encoded
- ** format. The program only operates on files stored in the original
- ** TGA format.
- **
- ** USAGE:
- ** tgapack [options] [file1] [file2] ...
- **
- ** If no filenames are provided, the program will prompt for a file
- ** name. If no extension is provided with a filename, the program
- ** will search for the file with ".tga", ".vst", ".icb", ".vda", or
- ** ".win" extension. Options are specified by a leading '-'.
- ** If no options are provided, the program attempts to compress an
- ** uncompressed image.
- **
- ** Recognized options are:
- **
- ** -unpack uncompressed a run length encoded image
- ** -32to24 compress a 32 bit image by eliminating alpha data
- ** -version report version number of program
- */
-
- #include <conio.h>
- #include <graph.h>
- #include <io.h>
- #include <malloc.h>
- #include <stdio.h>
- #include <stdlib.h>
- #include <string.h>
- #include <sys/types.h>
- #include <sys/stat.h>
- #include "tga.h"
-
- /*
- ** Define byte counts associated with extension areas for various
- ** versions of the TGA specification.
- */
- #define EXT_SIZE_20 495 /* verison 2.0 extension size */
-
- #define CBUFSIZE 2048 /* size of copy buffer */
- #define RLEBUFSIZ 512 /* size of largest possible RLE packet */
-
-
- extern void main( int, char ** );
- extern int CountDiffPixels( char *, int, int );
- extern long CountRLEData( FILE *, unsigned int, unsigned int, int );
- extern int CountSamePixels( char *, int, int );
- extern int DisplayImageData( unsigned char *, int, int );
- extern UINT32 GetPixel( unsigned char *, int );
- extern int OutputTGAFile( FILE *, FILE *, TGAFile * );
- extern int ParseArgs( int, char ** );
- extern void PrintImageType( int );
- extern void PrintTGAInfo( TGAFile * );
- extern UINT8 ReadByte( FILE * );
- extern void ReadCharField( FILE *, char *, int );
- extern UINT32 ReadLong( FILE * );
- extern int ReadRLERow( unsigned char *, int, int, FILE * );
- extern UINT16 ReadShort( FILE * );
- extern int RLEncodeRow( char *, char *, int, int );
- extern char *SkipBlank( char * );
- extern void StripAlpha( unsigned char *, int );
- extern int WriteByte( UINT8, FILE * );
- extern int WriteLong( UINT32, FILE * );
- extern int WriteShort( UINT16, FILE * );
- extern int WriteStr( char *, int, FILE * );
-
-
- /*
- ** String data for interpretting image orientation specification
- */
- char *orientStr[] =
- {
- "Bottom Left",
- "Bottom Right",
- "Top Left",
- "Top Right"
- };
-
- /*
- ** String data for interpretting interleave flag defined with VDA
- ** This field is now obsolete and should typically be set to zero.
- */
- char *interleaveStr[] =
- {
- " Two Way (Even-Odd) Interleave (e.g., IBM Graphics Card Adapter), Obsolete",
- " Four Way Interleave (e.g., AT&T 6300 High Resolution), Obsolete",
- };
-
-
- /*
- ** Filename extensions used during file search
- */
- char *extNames[] =
- {
- ".tga",
- ".vst",
- ".icb",
- ".vda",
- ".win",
- NULL
- };
-
- TGAFile f; /* control structure of image data */
-
- int unPack; /* when true, uncompress image data */
- int noAlpha; /* when true, converts 32 bit image to 24 */
-
- int inRawPacket; /* flags processing state for RLE data */
- int inRLEPacket; /* flags processing state for RLE data */
- unsigned int packetSize; /* records current RLE packet size in bytes */
- char rleBuf[RLEBUFSIZ];
-
- char copyBuf[CBUFSIZE];
-
-
- char *versionStr =
- "Truevision(R) TGA(tm) File Compression Utility Version 1.3 - January 2, 1990";
-
-
- void
- main( argc, argv )
- int argc;
- char **argv;
- {
- int fileFound;
- int fileCount;
- int files;
- char *q;
- FILE *fp, *outFile;
- int i;
- char fileName[80];
- char outFileName[80];
- struct stat statbuf;
-
- unPack = 0; /* default to compressing image data */
- noAlpha = 0; /* default to retaining all components of 32 bit */
-
- inRawPacket = inRLEPacket = 0; /* initialize RLE processing flags */
- packetSize = 0;
- /*
- ** The program can be invoked without an argument, in which case
- ** the user will be prompted for the name of the image file to be
- ** examined, or the image file name can be provided as an argument
- ** to the command.
- **
- ** File names provided do not need to include the extension if
- ** the image file extension is one of the standard strings common
- ** to Truevision TGA image file names ( e.g., TGA, WIN, VST, VDA, ICB )
- */
- if ( argc == 1 )
- {
- puts( versionStr );
- printf( "Enter name of file to examine: " );
- gets( fileName );
- if ( strlen( fileName ) == 0 ) exit( 0 );
- fileCount = 1;
- }
- else
- {
- fileCount = ParseArgs( argc, argv );
- if ( fileCount == 0 ) exit( 0 );
- argv++;
- while ( **argv == '-' ) argv++;
- strcpy( fileName, *argv );
- }
- for ( files = 0; files < fileCount; ++files )
- {
- if ( files != 0 )
- {
- argv++;
- while ( **argv == '-' ) argv++;
- strcpy( fileName, *argv );
- }
- /*
- ** See if we can find the file as specified or with one of the
- ** standard filename extensions...
- */
- fileFound = 0;
- if ( stat( fileName, &statbuf ) == 0 ) fileFound = 1;
- else
- {
- /*
- ** If there is already an extension specified, skip
- ** the search for standard extensions
- */
- q = strchr( fileName, '.' );
- if ( q != NULL )
- {
- q = fileName + strlen( fileName );
- }
- else
- {
- i = 0;
- strcat( fileName, extNames[i] );
- q = strchr( fileName, '.' );
- while ( extNames[i] != NULL )
- {
- strcpy( q, extNames[i] );
- if ( stat( fileName, &statbuf ) == 0 )
- {
- fileFound = 1;
- break;
- }
- ++i;
- }
- }
- }
- if ( fileFound )
- {
- _clearscreen( _GCLEARSCREEN );
- printf( "Processing TGA File: %s\n", fileName );
- fp = fopen( fileName, "rb" );
- /*
- ** It would be nice to be able to read in the entire
- ** structure with one fread, but compiler dependent
- ** structure alignment precludes the simplistic approach.
- ** Instead, fill each field individually, and use routines
- ** that will allow code to execute on various hosts by
- ** recompilation with particular compiler flags.
- **
- ** Start by reading the fields associated with the original
- ** TGA format.
- */
- f.idLength = ReadByte( fp );
- f.mapType = ReadByte( fp );
- f.imageType = ReadByte( fp );
- f.mapOrigin = ReadShort( fp );
- f.mapLength = ReadShort( fp );
- f.mapWidth = ReadByte( fp );
- f.xOrigin = ReadShort( fp );
- f.yOrigin = ReadShort( fp );
- f.imageWidth = ReadShort( fp );
- f.imageHeight = ReadShort( fp );
- f.pixelDepth = ReadByte( fp );
- f.imageDesc = ReadByte( fp );
- memset( f.idString, 0, 256 );
- if ( f.idLength > 0 )
- {
- fread( f.idString, 1, f.idLength, fp );
- }
- /*
- ** Now see if the file is the new (extended) TGA format.
- */
- if ( !fseek( fp, statbuf.st_size - 26, SEEK_SET ) )
- {
- f.extAreaOffset = ReadLong( fp );
- f.devDirOffset = ReadLong( fp );
- fgets( f.signature, 18, fp );
- if ( strcmp( f.signature, "TRUEVISION-XFILE." ) )
- {
- /*
- ** Reset offset values since this is not a new TGA file
- */
- f.extAreaOffset = 0L;
- f.devDirOffset = 0L;
-
- strcpy( outFileName, fileName );
- i = strlen( fileName );
- outFileName[ i - 3 ] = '\0'; /* remove extension */
- strcat( outFileName, "$$$" );
- if ( ( outFile = fopen( outFileName, "wb" ) ) != NULL )
- {
- if ( OutputTGAFile( fp, outFile, &f ) < 0 )
- {
- fclose( outFile );
- unlink( outFileName );
- }
- else
- {
- fclose( outFile );
- fclose( fp );
- fp = (FILE *)0;
- unlink( fileName );
- rename( outFileName, fileName );
- }
- }
- else
- {
- puts( "Unable to create output file." );
- }
- }
- else puts( "Input file must be original TGA format." );
- }
- else
- {
- puts( "Error seeking to end of file for possible extension data." );
- }
- if ( fp != NULL ) fclose( fp );
- }
- else
- {
- *q = '\0';
- printf("Unable to open image file %s\n", fileName );
- }
- }
- }
-
-
-
- /*
- ** Count pixels in buffer until two identical adjacent ones found
- */
-
- int
- CountDiffPixels( p, bpp, pixCnt )
- char *p;
- int bpp;
- int pixCnt;
- {
- unsigned long pixel;
- unsigned long nextPixel;
- int n;
-
- n = 0;
- if ( pixCnt == 1 ) return( pixCnt );
- pixel = GetPixel( p, bpp );
- while ( pixCnt > 1 )
- {
- p += bpp;
- nextPixel = GetPixel( p, bpp );
- if ( nextPixel == pixel ) break;
- pixel = nextPixel;
- ++n;
- --pixCnt;
- }
- if ( nextPixel == pixel ) return( n );
- return( n + 1 );
- }
-
-
-
- long
- CountRLEData( fp, x, y, bytesPerPixel )
- FILE *fp;
- unsigned int x;
- unsigned int y;
- int bytesPerPixel;
- {
- long n;
- long pixelCount;
- long totalPixels;
- unsigned int value;
-
- n = 0L;
- pixelCount = 0L;
- totalPixels = (long)x * (long)y;
-
- while ( pixelCount < totalPixels )
- {
- value = (unsigned int)ReadByte( fp );
- n++;
- if ( value & 0x80 )
- {
- n += bytesPerPixel;
- pixelCount += (value & 0x7f) + 1;
- if ( fread( copyBuf, 1, bytesPerPixel, fp ) != bytesPerPixel )
- {
- puts( "Error counting RLE data." );
- return( 0L );
- }
- }
- else
- {
- value++;
- n += value * bytesPerPixel;
- pixelCount += value;
- if ( fread( copyBuf, bytesPerPixel, value, fp ) != value )
- {
- puts( "Error counting raw data." );
- return( 0L );
- }
- }
- }
- return( n );
- }
-
-
-
- int
- CountSamePixels( p, bpp, pixCnt )
- char *p;
- int bpp;
- int pixCnt;
- {
- unsigned long pixel;
- unsigned long nextPixel;
- int n;
-
- n = 1;
- pixel = GetPixel( p, bpp );
- pixCnt--;
- while ( pixCnt > 0 )
- {
- p += bpp;
- nextPixel = GetPixel( p, bpp );
- if ( nextPixel != pixel ) break;
- ++n;
- --pixCnt;
- }
- return( n );
- }
-
-
-
-
- int
- DisplayImageData( q, n, bpp )
- unsigned char *q;
- int n;
- int bpp;
- {
- long i;
- int j;
- unsigned char a, b, c;
-
- i = 0;
- while ( i < n )
- {
- printf( "%08lX: ", i );
- switch ( bpp )
- {
- case 4:
- for ( j = 0; j < 4; ++j )
- {
- printf( "%08lx ", *(unsigned long *)q );
- q += 4;
- }
- i += 16;
- break;
- case 3:
- for ( j = 0; j < 8; ++j )
- {
- a = *q++;
- b = *q++;
- c = *q++;
- printf( "%02x%02x%02x ", c, b, a );
- }
- i += 24;
- break;
- case 2:
- for ( j = 0; j < 8; ++j )
- {
- printf( "%04x ", *(unsigned int *)q );
- q += 2;
- }
- i += 16;
- break;
- default:
- for ( j = 0; j < 16; ++j )
- {
- printf( "%02x ", *(unsigned char *)q++ );
- }
- i += 16;
- break;
- }
- putchar( '\n' );
- }
- return( 0 );
- }
-
-
-
- /*
- ** Retrieve a pixel value from a buffer. The actual size and order
- ** of the bytes is not important since we are only using the value
- ** for comparisons with other pixels.
- */
-
- unsigned long
- GetPixel( p, bpp )
- unsigned char *p;
- int bpp; /* bytes per pixel */
- {
- unsigned long pixel;
-
- pixel = (unsigned long)*p++;
- while ( bpp-- > 1 )
- {
- pixel <<= 8;
- pixel |= (unsigned long)*p++;
- }
- return( pixel );
- }
-
-
-
- int
- OutputTGAFile( ifp, ofp, sp )
- FILE *ifp; /* input file pointer */
- FILE *ofp; /* output file pointer */
- TGAFile *sp; /* output TGA structure */
- {
- long byteCount;
- unsigned long fileOffset;
- int i;
- int bytesPerPixel;
- int bCount;
- int rleCount;
- unsigned char *imageBuff;
- unsigned char *packBuff;
- unsigned char outType;
- unsigned char outDepth;
- unsigned char outDesc;
-
- /*
- ** First, we need to determine what operation is to be performed.
- ** We could be run length encoding an uncompressed image, or
- ** we could be uncompressing an RLE image. Or we could be compacting
- ** a 32 bit image to a 24 bit image.
- */
- if ( noAlpha )
- {
- if ( sp->pixelDepth != 32 || sp->imageType != 2 )
- {
- puts( "Image file must be in 32 bit uncompressed format." );
- return( -1 );
- }
- else
- {
- outDepth = 24;
- outType = sp->imageType;
- outDesc = sp->imageDesc & 0xf0;
- }
- }
- else if ( !unPack && sp->imageType > 0 && sp->imageType < 4 )
- {
- outType = sp->imageType + 8;
- outDepth = sp->pixelDepth;
- outDesc = sp->imageDesc;
- }
- else if ( unPack && sp->imageType > 8 && sp->imageType < 12 )
- {
- outType = sp->imageType - 8;
- outDepth = sp->pixelDepth;
- outDesc = sp->imageDesc;
- }
- else
- {
- puts( "File type is inconsistent with requested operation." );
- return( -1 );
- }
- /*
- ** The output file was just opened, so the first data
- ** to be written is the standard header based on the
- ** original TGA specification.
- */
- if ( WriteByte( sp->idLength, ofp ) < 0 ) return( -1 );
- if ( WriteByte( sp->mapType, ofp ) < 0 ) return( -1 );
- if ( WriteByte( outType, ofp ) < 0 ) return( -1 );
- if ( WriteShort( sp->mapOrigin, ofp ) < 0 ) return( -1 );
- if ( WriteShort( sp->mapLength, ofp ) < 0 ) return( -1 );
- if ( WriteByte( sp->mapWidth, ofp ) < 0 ) return( -1 );
- if ( WriteShort( sp->xOrigin, ofp ) < 0 ) return( -1 );
- if ( WriteShort( sp->yOrigin, ofp ) < 0 ) return( -1 );
- if ( WriteShort( sp->imageWidth, ofp ) < 0 ) return( -1 );
- if ( WriteShort( sp->imageHeight, ofp ) < 0 ) return( -1 );
- if ( WriteByte( outDepth, ofp ) < 0 ) return( -1 );
- if ( WriteByte( outDesc, ofp ) < 0 ) return( -1 );
- if ( sp->idLength )
- {
- if ( WriteStr( sp->idString, sp->idLength, ofp ) < 0 )
- return( -1 );
- }
- /*
- ** Now we need to copy the color map data from the input file
- ** to the output file.
- */
- byteCount = 18 + sp->idLength;
- if ( fseek( ifp, byteCount, SEEK_SET ) != 0 ) return( -1 );
- byteCount = ((sp->mapWidth + 7) >> 3) * (long)sp->mapLength;
- fileOffset = 18 + sp->idLength + byteCount;
- while ( byteCount > 0 )
- {
- if ( byteCount - CBUFSIZE < 0 )
- {
- fread( copyBuf, 1, (int)byteCount, ifp );
- if ( fwrite( copyBuf, 1, (int)byteCount, ofp ) != (int)byteCount )
- return( -1 );
- }
- else
- {
- fread( copyBuf, 1, CBUFSIZE, ifp );
- if ( fwrite( copyBuf, 1, CBUFSIZE, ofp ) != CBUFSIZE )
- return( -1 );
- }
- byteCount -= CBUFSIZE;
- }
- /*
- ** Now process the image data.
- */
- bytesPerPixel = (sp->pixelDepth + 7) >> 3;
- bCount = sp->imageWidth * bytesPerPixel;
- if ( (imageBuff = malloc( bCount )) == NULL )
- {
- puts( "Unable to allocate image buffer" );
- return( -1 );
- }
-
- if ( noAlpha )
- {
- for ( i = 0; i < sp->imageHeight; ++i )
- {
- if ( fread( imageBuff, 1, bCount, ifp ) != bCount )
- {
- puts( "Error reading uncompressed data." );
- free( imageBuff );
- return( -1 );
- }
- StripAlpha( imageBuff, bCount );
- if ( fwrite( imageBuff, 1, bCount - sp->imageWidth, ofp ) !=
- bCount - sp->imageWidth )
- {
- puts( "Error writing 24 bit image data." );
- free( imageBuff );
- return( -1 );
- }
- }
- }
- else if ( !unPack )
- {
- if ( (packBuff = malloc( sp->imageWidth * (bytesPerPixel + 1) )) == NULL )
- {
- puts( "Error allocating encoded buffer." );
- free( imageBuff );
- return( -1 );
- }
- for ( i = 0; i < sp->imageHeight; ++i )
- {
- if ( fread( imageBuff, 1, bCount, ifp ) != bCount )
- {
- puts( "Error reading uncompressed data." );
- free( imageBuff );
- free( packBuff );
- return( -1 );
- }
- rleCount = RLEncodeRow( imageBuff, packBuff, sp->imageWidth,
- bytesPerPixel );
- if ( fwrite( packBuff, 1, rleCount, ofp ) != rleCount )
- {
- puts( "Error writing RLE image data." );
- free( imageBuff );
- free( packBuff );
- return( -1 );
- }
- }
- free( packBuff );
- }
- else
- {
- /*
- ** Uncompress image data
- */
- for ( i = 0; i < sp->imageHeight; ++i )
- {
- if ( ReadRLERow( imageBuff, bCount, bytesPerPixel, ifp ) < 0 )
- {
- puts("Error reading RLE data." );
- free( imageBuff );
- return( -1 );
- }
- if ( fwrite( imageBuff, 1, bCount, ofp ) != bCount )
- {
- puts("Error writing uncompressed data." );
- free( imageBuff );
- return( -1 );
- }
- }
- }
- free( imageBuff );
-
- return( 0 );
- }
-
-
-
- int
- ParseArgs( argc, argv )
- int argc;
- char **argv;
- {
- int i;
- int n;
- char *p;
-
- n = 0;
- for ( i = 1; i < argc; ++i )
- {
- p = *(++argv);
- if ( *p == '-' )
- {
- p++;
- if ( stricmp( p, "unpack" ) == 0 ) unPack = 1;
- else if ( stricmp( p, "32to24" ) == 0 ) noAlpha = 1;
- else if ( stricmp( p, "version" ) == 0 )
- {
- puts( versionStr );
- exit( 0 );
- }
- else
- {
- puts( "Usage: tgapack [options] [file1] [file2...]" );
- puts( " where options can be:" );
- puts( " -unpack\t\tuncompress image data" );
- puts( " -32to24\t\tconvert 32 bit image to 24 bit image" );
- puts( " -version\t\treport version number" );
- exit( 0 );
- }
- }
- else ++n;
- }
- return( n );
- }
-
-
-
-
- void
- PrintImageType( Itype )
- register int Itype;
- {
- if ( Itype > 255 || Itype < 0 )
- {
- puts("Illegal/Undefined Image Type");
- return;
- }
-
- if ( Itype > 127 )
- {
- puts("Unknown Image Type - Application Specific");
- return;
- }
-
- switch (Itype)
- {
- case 0:
- puts("Unknown Image Type - No Image Data Present");
- break;
- case 1:
- puts("Uncompressed Color Mapped Image (e.g., VDA/D, TARGA M8)");
- break;
- case 2:
- puts("Uncompressed True Color Image (e.g., ICB, TARGA 16/24/32)");
- break;
- case 3:
- puts("Uncompressed Black & White Image (e.g., TARGA 8/M8)");
- break;
- case 9:
- puts("Run Length Encoded Color Mapped Image (e.g., VDA/D, TARGA M8)");
- break;
- case 10:
- puts("Run Length Encoded True Color Image (e.g., ICB, TARGA 16/24/32)");
- break;
- case 11:
- puts("Compressed Black & White Image (e.g., TARGA 8/M8)");
- break;
- case 32:
- case 34:
- puts("Compressed (Huffman/Delta/RLE) Color Mapped Image (e.g., VDA/D) - Obsolete");
- break;
- case 33:
- case 35:
- puts("Compressed (Huffman/Delta/RLE) Color Mapped Four Pass Image (e.g., VDA/D) - Obsolete");
- break;
- default:
- puts("Unknown Image Type");
- break;
- }
- }
-
-
-
-
- void
- PrintTGAInfo( sp )
- TGAFile *sp; /* TGA structure pointer */
- {
- int i;
-
- printf("ID Field Length = %3d\n", sp->idLength);
-
- printf("Color Map Type = %3d (Color Map Data is ", sp->mapType);
- if (sp->mapType) puts("Present)");
- else puts("Absent)");
-
- printf("Image Type = %3d\n ", sp->imageType);
- PrintImageType( sp->imageType );
-
- printf("Color Map Origin = 0x%04x (%5d)",
- sp->mapOrigin, sp->mapOrigin);
- puts( " (First Index To Be Loaded)" );
- printf("Color Map Length = 0x%04x (%5d)\n",
- sp->mapLength,sp->mapLength);
- printf("Color Map Entry Size = %6d\n", sp->mapWidth);
-
- printf("Image X-Origin, Y-Origin = %05d, %05d\n",
- sp->xOrigin, sp->yOrigin);
- printf("Image Width, Height = %05d, %05d\n",
- sp->imageWidth, sp->imageHeight);
-
- printf("Image Pixel Depth = 0x%04x (%05d)\n",
- sp->pixelDepth, sp->pixelDepth);
- printf("Image Descriptor = 0x%04x\n", sp->imageDesc);
- printf(" %d Attribute Bits Per Pixel\n", sp->imageDesc & 0xf );
- printf(" First Pixel Destination is ");
-
- i = (sp->imageDesc & 0x30) >> 4;
- puts( orientStr[i] );
-
- i = (sp->imageDesc & 0xc0) >> 6;
- if ( i > 0 && i < 3 ) puts( interleaveStr[i - 1] );
-
- if ( sp->idLength )
- {
- printf( "Image ID:\n " );
- puts( f.idString );
- }
- }
-
-
- UINT8
- ReadByte( fp )
- FILE *fp;
- {
- UINT8 value;
-
- #if MSDOS
- fread( &value, 1, 1, fp );
- #else
- #endif
- return( value );
- }
-
-
- void
- ReadCharField( fp, p, n )
- FILE *fp;
- char *p;
- int n;
- {
- while ( n )
- {
- *p++ = (char)fgetc( fp ); /* no error check, no char conversion */
- --n;
- }
- }
-
-
-
-
- UINT32
- ReadLong( fp )
- FILE *fp;
- {
- UINT32 value;
-
- #if MSDOS
- fread( &value, 4, 1, fp );
- #else
- #endif
- return( value );
- }
-
-
-
- int
- ReadRLERow( p, n, bpp, fp )
- unsigned char *p;
- int n; /* buffer size in bytes */
- int bpp; /* bytes per pixel */
- FILE *fp;
- {
- unsigned int value;
- int i;
- static unsigned char *q;
-
- while ( n > 0 )
- {
- if ( inRLEPacket )
- {
- if ( packetSize * bpp > n )
- {
- value = n / bpp; /* calculate pixel count */
- packetSize -= value;
- n = 0;
- }
- else
- {
- n -= packetSize * bpp;
- value = packetSize;
- packetSize = 0;
- inRLEPacket = 0;
- }
- while ( value > 0 )
- {
- *p++ = rleBuf[0];
- if ( bpp > 1 ) *p++ = rleBuf[1];
- if ( bpp > 2 ) *p++ = rleBuf[2];
- if ( bpp > 3 ) *p++ = rleBuf[3];
- value--;
- }
- }
- else if ( inRawPacket )
- {
- if ( packetSize * bpp > n )
- {
- value = n;
- packetSize -= n / bpp;
- n = 0;
- }
- else
- {
- value = packetSize * bpp; /* calculate byte count */
- n -= value;
- inRawPacket = 0;
- }
- for ( i = 0; i < value; ++i ) *p++ = *q++;
- }
- else
- {
- /*
- ** No accumulated data in buffers, so read from file
- */
- packetSize = (unsigned int)ReadByte( fp );
- if ( packetSize & 0x80 )
- {
- packetSize &= 0x7f;
- packetSize++;
- if ( packetSize * bpp > n )
- {
- value = n / bpp; /* calculate pixel count */
- packetSize -= value;
- inRLEPacket = 1;
- n = 0;
- }
- else
- {
- n -= packetSize * bpp;
- value = packetSize;
- }
- if ( fread( rleBuf, 1, bpp, fp ) != bpp ) return( -1 );
- while ( value > 0 )
- {
- *p++ = rleBuf[0];
- if ( bpp > 1 ) *p++ = rleBuf[1];
- if ( bpp > 2 ) *p++ = rleBuf[2];
- if ( bpp > 3 ) *p++ = rleBuf[3];
- value--;
- }
- }
- else
- {
- packetSize++;
- /*
- ** Maximum for packetSize is 128 so as long as RLEBUFSIZ
- ** is at least 512, and bpp is not greater than 4
- ** we can read in the entire raw packet with one operation.
- */
- if ( fread( rleBuf, bpp, packetSize, fp ) != packetSize )
- return( -1 );
- /*
- ** But is there enough room to copy them to our line buffer?
- */
- if ( packetSize * bpp > n )
- {
- value = n; /* number of bytes remaining */
- packetSize -= n / bpp;
- inRawPacket = 1;
- n = 0;
- }
- else
- {
- value = packetSize * bpp; /* calculate byte count */
- n -= value;
- }
- for ( i = 0, q = rleBuf; i < value; ++i ) *p++ = *q++;
- }
- }
- }
- return( 0 );
- }
-
-
-
-
- UINT16
- ReadShort( fp )
- FILE *fp;
- {
- UINT16 value;
-
- #if MSDOS
- fread( &value, 2, 1, fp );
- #else
- #endif
- return( value );
- }
-
-
-
- int
- RLEncodeRow( p, q, n, bpp )
- char *p; /* data to be encoded */
- char *q; /* encoded buffer */
- int n; /* number of pixels in buffer */
- int bpp; /* bytes per pixel */
- {
- int diffCount; /* pixel count until two identical */
- int sameCount; /* number of identical adjacent pixels */
- int RLEBufSize; /* count of number of bytes encoded */
-
- RLEBufSize = 0;
- while ( n > 0 )
- {
- diffCount = CountDiffPixels( p, bpp, n );
- sameCount = CountSamePixels( p, bpp, n );
- if ( diffCount > 128 ) diffCount = 128;
- if ( sameCount > 128 ) sameCount = 128;
- if ( diffCount > 0 )
- {
- /* create a raw packet */
- *q++ = (char)(diffCount - 1);
- n -= diffCount;
- RLEBufSize += (diffCount * bpp) + 1;
- while ( diffCount > 0 )
- {
- *q++ = *p++;
- if ( bpp > 1 ) *q++ = *p++;
- if ( bpp > 2 ) *q++ = *p++;
- if ( bpp > 3 ) *q++ = *p++;
- diffCount--;
- }
- }
- if ( sameCount > 1 )
- {
- /* create a RLE packet */
- *q++ = (char)((sameCount - 1) | 0x80);
- n -= sameCount;
- RLEBufSize += bpp + 1;
- p += (sameCount - 1) * bpp;
- *q++ = *p++;
- if ( bpp > 1 ) *q++ = *p++;
- if ( bpp > 2 ) *q++ = *p++;
- if ( bpp > 3 ) *q++ = *p++;
- }
- }
- return( RLEBufSize );
- }
-
-
-
- char *
- SkipBlank( p )
- char *p;
- {
- while ( *p != '\0' && (*p == ' ' || *p == '\t') ) ++p;
- return( p );
- }
-
-
-
- void
- StripAlpha( s, n )
- unsigned char *s;
- int n;
- {
- int i;
- unsigned char *p;
-
- /*
- ** Copy the RGB components omitting the alpha. Perform the
- ** copy in its own buffer. This algorithm is probably
- ** specific to the 80x86 since byte orderring will be different
- ** on a 680x0 processor.
- */
- p = s;
- for ( i = 0; i < n; ++i )
- {
- if ( ( i % 4) == 3 ) ++p;
- else *s++ = *p++;
- }
- }
-
-
- int
- WriteByte( uc, fp )
- UINT8 uc;
- FILE *fp;
- {
- #ifdef MSDOS
- if ( fwrite( &uc, 1, 1, fp ) == 1 ) return( 0 );
- #else
- #endif
- return( -1 );
- }
-
-
-
- int
- WriteLong( ul, fp )
- UINT32 ul;
- FILE *fp;
- {
- #ifdef MSDOS
- if ( fwrite( &ul, 4, 1, fp ) == 1 ) return( 0 );
- #else
- #endif
- return( -1 );
- }
-
-
- int
- WriteShort( us, fp )
- UINT16 us;
- FILE *fp;
- {
- #ifdef MSDOS
- if ( fwrite( &us, 2, 1, fp ) == 1 ) return( 0 );
- #else
- #endif
- return( -1 );
- }
-
-
- int
- WriteStr( p, n, fp )
- char *p;
- int n;
- FILE *fp;
- {
- #ifdef MSDOS
- if ( fwrite( p, 1, n, fp ) == n ) return( 0 );
- #else
- #endif
- return( -1 );
- }
-