www.pudn.com > DlgScrSaver.rar > PCX.cpp
#include "stdafx.h" #include "PCX.h" #include#include /* ZSoft .PCX FILE HEADER FORMAT Byte Item Size Description/Comments 0 Manufacturer 1 Constant Flag, 10 = ZSoft .pcx 1 Version 1 Version information 0 = Version 2.5 of PC Paintbrush 2 = Version 2.8 w/palette information 3 = Version 2.8 w/o palette information 4 = PC Paintbrush for Windows(Plus for Windows uses Ver 5) 5 = Version 3.0 and > of PC Paintbrush and PC Paintbrush +, includes Publisher's Paintbrush . Includes 24-bit .PCX files 2 Encoding 1 1 = .PCX run length encoding 3 BitsPerPixel 1 Number of bits to represent a pixel (per Plane) - 1, 2, 4, or 8 4 Window 8 Image Dimensions: Xmin,Ymin,Xmax,Ymax 12 HDpi 2 Horizontal Resolution of image in DPI* 14 VDpi 2 Vertical Resolution of image in DPI* 16 Colormap 48 Color palette setting, see text 64 Reserved 1 Should be set to 0. 65 NPlanes 1 Number of color planes 66 BytesPerLine 2 Number of bytes to allocate for a scanline plane. MUST be an EVEN number. Do NOT calculate from Xmax-Xmin. 68 PaletteInfo 2 How to interpret palette- 1 = Color/BW, 2 = Grayscale (ignored in PB IV/ IV +) 70 HscreenSize 2 Horizontal screen size in pixels. New field found only in PB IV/IV Plus 72 VscreenSize 2 Vertical screen size in pixels. New field found only in PB IV/IV Plus 74 Filler 54 Blank to fill out 128 byte header. Set all bytes to 0 */ //The following is a simple set of C subroutines to read data from a .PCX file. /* This procedure reads one encoded block from the image file and stores a count and data byte. Return result: 0 = valid data stored, EOF = out of data in file */ /* int *pbyt; // where to place data int *pcnt; // where to place count FILE *fid; // image file handle */ int encget(int* pbyt, int* pcnt, FILE* fid) { int i; *pcnt = 1; /* assume a "run" length of one */ if (EOF == (i = getc(fid))) return (EOF); if (0xC0 == (0xC0 & i)) { *pcnt = 0x3F & i; if (EOF == (i = getc(fid))) return (EOF); } *pbyt = i; return (0); } /* Here's a program fragment using encget. This reads an entire file and stores it in a (large) buffer, pointed to by the variable "bufr". "fp" is the file pointer for the image */ bool ReadPCX(BYTE* bufr, PCXHEADER& hdr, FILE* fp) { int i; long l, lsize; int chr, cnt; lsize = (long )hdr.BytesPerLine * hdr.NPlanes * (1 + hdr.Ymax - hdr.Ymin); for (l = 0; l < lsize; ) /* increment by cnt below */ { if (EOF == encget(&chr, &cnt, fp)) break; for (i = 0; i < cnt; i++) *bufr++ = chr; l += cnt; } return true; } BYTE* ReadPCX(const char* fname, PCXHEADER& hdr) { FILE* fp = fopen(fname, "r"); if (fp == NULL) return NULL; //PCXHEADER hdr; if (fread(&hdr, 1, 128, fp) != 128) return NULL; BYTE* buffer = (BYTE*)GlobalAllocPtr(GMEM_FIXED | GMEM_ZEROINIT, (hdr.Xmax-hdr.Xmin+1) * (hdr.Ymax-hdr.Ymin+1)); if (buffer == NULL) return NULL; ReadPCX(buffer, hdr, fp); fclose(fp); return buffer; } void DisplayPCX(CDC* pDC, CRect& rect, PCXHEADER& hdr, BYTE* buffer) { ofstream os("c:\\testpcx.txt"); os << (int)hdr.Manufacturer << endl; os << (int)hdr.Version << endl; os << (int)hdr.Encoding << endl; os << (int)hdr.BitsPerPixel << endl; os << hdr.Xmin << endl; os << hdr.Ymin << endl; os << hdr.Xmax << endl; os << hdr.Ymax << endl; os << hdr.HDpi << endl; os << hdr.VDpi << endl; //os << hdr.ColorMap[48] << endl; os << (int)hdr.Reserved << endl; os << (int)hdr.NPlanes << endl; os << hdr.BytesPerLine << endl; os << hdr.PaletteInfo << endl; os << hdr.HscreenSize << endl; os << hdr.VscreenSize << endl; for (int i=hdr.Ymin; i<=hdr.Ymin; i++) { for (int j=hdr.Xmin; j<=hdr.Xmin; j++) { int index = (i-hdr.Ymin) * (hdr.Xmax-hdr.Xmin+1) + j-hdr.Xmin; BYTE pixel = buffer[index]; os << pixel << endl; } } } //The following is a set of C subroutines to write data to a .PCX file. /* Subroutine for writing an encoded byte pair (or single byte if it doesn't encode) to a file. It returns the count of bytes written, 0 if error */ /* unsigned char byt, cnt; FILE *fid; */ int encput(unsigned char byt, unsigned char cnt, FILE* fid) { if (cnt) { if ((cnt == 1) && (0xC0 != (0xC0 & byt))) { if (EOF == putc((int )byt, fid)) return(0); /* disk write error (probably full) */ return(1); } else { if (EOF == putc((int )0xC0 | cnt, fid)) return (0); /* disk write error */ if (EOF == putc((int )byt, fid)) return (0); /* disk write error */ return (2); } } return (0); } /* This subroutine encodes one scanline and writes it to a file. It returns number of bytes written into outBuff, 0 if failed. */ /* unsigned char *inBuff; // pointer to scanline data int inLen; // length of raw scanline in bytes FILE *fp; // file to be written to */ int encLine(unsigned char* inBuff, int inLen, FILE* fp) { unsigned char This, Last; int srcIndex, i; register int total; register unsigned char runCount; /* max single runlength is 63 */ total = 0; runCount = 1; Last = *(inBuff); /* Find the pixel dimensions of the image by calculating [XSIZE = Xmax - Xmin + 1] and [YSIZE = Ymax - Ymin + 1]. Then calculate how many bytes are in a "run" */ for (srcIndex = 1; srcIndex < inLen; srcIndex++) { This = *(++inBuff); if (This == Last) /* There is a "run" in the data, encode it */ { runCount++; if (runCount == 63) { if (! (i = encput(Last, runCount, fp))) return (0); total += i; runCount = 0; } } else /* No "run" - this != last */ { if (runCount) { if (! (i = encput(Last, runCount, fp))) return(0); total += i; } Last = This; runCount = 1; } } /* endloop */ if (runCount) /* finish up */ { if (! (i = encput(Last, runCount, fp))) return (0); return (total + i); } return (total); }