/* PCX_IO.C - source code for functions in PCX_IO.LIB * * Jeff Lucius * Geophysicist * U.S. Geological Survey * Geologic Division, Branch of Geophysics * Box 25046 Denver Federal Center MS 964 * Denver, CO 80225-0046 * 303-236-1413 (office), 303-236-1212 (secretary), 303-236-1425 (fax) * email: lucius@musette.cr.usgs.gov * * To compile for use in PCX.LIB: * icc /F /xnovm /zmod486 /zfloatsync /c PCX.C * * /F removes the floating point emulator, reduces binary size * /xnovm specifies no virtual memory manager, disk access is too slow * /zmod486 generates specific 80486 instructions, speeds up program. * /zfloatsync insures the FPU is operand-synchronized with the CPU. * /c compiles only, no linking. * * Functions in this module: * PcxDecodeScanLine * PcxEncodeScanLine * SetPcxHeader */ /* Include header files */ #include "pcx_io.h" /* Declare globals */ /**************************** PcxDecodeScanLine() ***************************/ /* Decode (uncompress) a PCX image file scan line. * * PcxDecodeScanLine() decodes a buffer containing scan line data encoded * using the PCX run-length encoding (RLE) algorithm. The encoded data is * read from a FILE stream, decoded, and then written to a pointer to a * buffer passed to this function. * * The PCX specification states (in so many words) that the run-length * encoding of a pixel run should stop at the end of each scan line. * However, some PCX encoders may continue the encoding of a pixel run on * to the beginning of the next scan line, if possible. This code, * therefore, assumes that any pixel run can span scan lines. * * NOTE: To check for decoding errors, the value returned by this function * should be the same as the value of BufferSize (the length of an * uncompressed scan line). * * Parameter list: * unsigned char *DecodedBuffer - pointer to buffer to hold decoded image data * int BufferSize - size of DecodedBuffer * FILE *infile - FILE pointer to the open input PCX image file * * Requires: , "pcx_jl.h". * Calls: fread,ferror,clearerr. * Returns: Total number of pixels decoded from compressed scan line, * or EOF (usually -1) if a file stream error occured. * * Author: Jeff Lucius USGS Branch of Geophysics Golden, CO * Modified from: * James D. Murray and William vanRyper, 1994, Encyclopedia of Graphics * File Formats: Sebastopol, CA, USA, O'Reilly & Assoc. Inc., 894 p. + * 1 CD-ROM. * Date: January 18, 1996 */ int PcxDecodeScanLine (unsigned char *DecodedBuffer,int BufferSize,FILE *infile) { int index = 0; /* index into compressed scan line buffer */ int total = 0; /* running total of decoded pixel values */ unsigned char byte; /* data byte read from PCX file */ static unsigned char runcount = 0; /* length of decoded pixel run */ static unsigned char runvalue = 0; /* value of decoded pixel run */ /* If there is any data left over from the previous scan line write it to the beginning of this scan line, using static variables. */ do { /* Write the pixel run to the buffer */ for (total+=runcount; runcount&&(index, "pcx_jl.h". * Calls: fread. * Returns: number of bytes in compressed (encoded) scan line. * * Author: Jeff Lucius USGS Branch of Geophysics Golden, CO * Modified from: * Encyclopedia of Graphics File Formats, 1994, James D. Murray and William * vanRyper: Sebastopol, CA, O'Reilly & Assoc. Inc., 894 p. + 1 CD-ROM. * Date: January 10, 1996 */ int PcxEncodeScanLine (unsigned char *DecodedBuffer,unsigned char *EncodedBuffer,int DecodedSize) { int decoded_index = 0; /* index into uncompressed (decoded) buffer */ int encoded_index = 0; /* index into compressed (endoded) buffer */ unsigned char runcount; /* length of encoded pixel run */ unsigned char runvalue; /* value of encoded pixel run */ while (decoded_index < DecodedSize) { /* Get the run count of the next pixel value run. Pixel value runs are encoded until a different pixel value is encountered, the end of the scan line is reached, or 63 pixel values have been counted. */ runvalue = DecodedBuffer[decoded_index]; for ( runcount = 1; (runvalue == DecodedBuffer[decoded_index + runcount]) && ((decoded_index + runcount) < DecodedSize) && (runcount < 63); runcount++) ; /* do nothing */ /* Encode the run into a one or two-byte code. Multiple pixel runs are stored in two-byte codes. If a single pixel run has a value of less than 64 then it is stored in a one-byte code. If a single pixel run has a value of 64 to 255 then it is stored in a two-byte code. */ if (runcount > 1) /* multiple pixel run */ { EncodedBuffer[encoded_index++] = runcount | 0xC0; EncodedBuffer[encoded_index++] = runvalue; } else /* single pixel run */ { if (DecodedBuffer[decoded_index] < 64) /* 1-byte code */ { EncodedBuffer[encoded_index++] = runvalue; } else /* 2-byte code */ { EncodedBuffer[encoded_index++] = runcount | 0xC0; EncodedBuffer[encoded_index++] = runvalue; } } decoded_index += runcount; /* jump ahead to next pixel run value */ } return(encoded_index); /* Return the number of bytes written to buffer */ } /****************************** SetPcxHeader() ******************************/ /* Set the members of a PCX header structure. * * Parameter list: * int BitsPerPixel - bits per pixel (1, 2, 4 or 8) * int X1 - left side of image (usually 0) * int Y1 - top side of image (usually 0) * int X2 - right side of image (pixels) * int Y2 - bottom side of image (pixels) * int HorDpi - horizontal pix/line or dots/in * int VerDpi - vertical pix/line or dots/in * int NumBitPlanes - number of color planes * int BytesPerLine - bytes in an unencoded scan line * int PaletteType - 1-monochrome; 2-gray scale * int HorScrnSize - horizontal Screen Size * int VerScrnSize - vertical screen size * struct PcxHdrStruct *HdrPtr - pointer to header structure * * Requires: , "pcx_jl.h". * Calls: memset. * Returns: void. * * Author: Jeff Lucius USGS Branch of Geophysics Golden, CO * Date: January 18, 1996 */ void SetPcxHeader (int BitsPerPixel,int X1,int Y1,int X2,int Y2, int HorDpi,int VerDpi,int NumBitPlanes,int BytesPerLine, int PaletteType,int HorScrnSize,int VerScrnSize, struct PcxHdrStruct *HdrPtr) { memset((void *)HdrPtr,0x00,sizeof(struct PcxHdrStruct)); HdrPtr->ID = 0x0A; HdrPtr->Version = 0x05; HdrPtr->Encoding = 0x01; HdrPtr->BitsPerPixel = (char)BitsPerPixel; HdrPtr->X1 = (short)X1; HdrPtr->Y1 = (short)Y1; HdrPtr->X2 = (short)X2; HdrPtr->Y2 = (short)Y2; HdrPtr->HorDpi = (short)HorDpi; HdrPtr->VerDpi = (short)VerDpi; HdrPtr->NumBitPlanes = (char)NumBitPlanes; HdrPtr->BytesPerLine = (short)BytesPerLine; HdrPtr->PaletteType = (short)PaletteType; HdrPtr->HorScrnSize = (short)HorScrnSize; HdrPtr->VerScrnSize = (short)VerScrnSize; }