www.pudn.com > 医学图像处理示例源代码.rar > GifFile.cpp


//////////////////////////////////////////////////////////// 
//	GIFFile - A C++ class to allow reading and writing of GIF Images 
// 
//	It is based on code from Programming for Graphics Files 
//	by John Levine 
// 
//	This is free to use and modify provided proper credit is given 
// 
//	This reads GIF 87a and 89a. 
// 
//	See GIFFile.h for example 
// 
//////////////////////////////////////////////////////////// 
#include "stdafx.h" 
#include  
#include  
#include  
#include  
#include  
#include  
#include "GifFile.h" 
 
#ifdef _DEBUG 
#undef THIS_FILE 
static char BASED_CODE THIS_FILE[] = __FILE__; 
#endif 
#define new DEBUG_NEW 
 
struct  
{ 
	unsigned int Width; 
	unsigned int Height; 
	unsigned char ColorMap[3][MAXCOLORMAPSIZE]; 
	unsigned int BitPixel; 
	unsigned int ColorResolution; 
	unsigned int BackGround; 
	unsigned int AspectRatio; 
} GifScreen; 
 
struct  
{ 
	int transparent; 
	int delayTime; 
	int inputFlag; 
	int disposal; 
} Gif89={-1,-1,-1,0}; 
 
GIFFile::GIFFile() 
{ 
	m_GIFErrorText="No Error"; // yet 
} 
 
GIFFile::~GIFFile() 
{ 
	// nothing 
} 
 
//****************************************************************************** 
// 
//	char * GIFFile::GIFReadInputFile(CString path,  
//								  UINT *width,  
//								  UINT *height) 
// 
//	Give a path. 
//	It will read the .GIF at that path, allocate a buffer and give you 
//	an RGB buffer back. width and height are modified to reflect the image dim's. 
// 
//	m_GIFErrorText is modifed to reflect error status 
// 
//****************************************************************************** 
BYTE * GIFFile::GIFReadFileToRGB(CString path, UINT *width,  UINT *height) 
{ 
	UCHAR			buf[16]; 
	UCHAR			c; 
	UCHAR			localColorMap[3][MAXCOLORMAPSIZE]; 
	int				useGlobalColormap; 
	int				bitPixel; 
	int				imageCount	=0; 
	char			version[4]; 
	FILE 			*fd;           
	int 			w=0; 
	int				h=0;	 
 
	if (path=="")  
	{ 
		m_GIFErrorText="No Name Given"; 
		return NULL; 
	} 
 
	BYTE *bigBuf; 
 
	fd = fopen(path,"rb"); 
	if( fd == NULL ) 
	{                        
		m_GIFErrorText = "Cant open GIF :\n" + path; 
		return NULL; 
	} 
 
	// read GIF file header 
	if( !ReadOK(fd, buf, 6) )  
	{ 
		m_GIFErrorText =" Error reading GIF Magic #\n"+path; 
		fclose(fd); 
		return NULL; 
	} 
	 
	// need the string "GIF" in the header 
	if( strncmp((char *)buf, "GIF", 3) != 0)  
	{ 
		m_GIFErrorText = "Error, "+ path+ " is not a valid .GIF file"; 
		fclose(fd); 
		return NULL; 
	}	 
 
	strncpy(version, (char *)(buf+3),3 ); 
	version[3] = '\0'; 
 
	// only handle v 87a and 89a 
	if ((strcmp(version, "87a")!=0)&&(strcmp(version,"89a")!=0)) 
	{ 
		m_GIFErrorText = "Error, Bad GIF Version number"; 
		fclose(fd); 
		return NULL; 
	}	 
 
	// screen description 
	if (!ReadOK(fd,buf,7))  
	{ 
		m_GIFErrorText="Error, failed to GIF read screen descriptor.\nGiving up"; 
		fclose(fd); 
		return NULL; 
	} 
 
	GifScreen.Width		=	LM_to_uint((UCHAR)buf[0],(UCHAR)buf[1]); 
	GifScreen.Height	=	LM_to_uint((UCHAR)buf[2],(UCHAR)buf[3]); 
	GifScreen.BitPixel	=	2 << ((UCHAR)buf[4] & 0x07); 
	GifScreen.ColorResolution = ((((UCHAR)buf[4] & 0x70) >> 3) + 1); 
	GifScreen.BackGround  =	(UCHAR)buf[5];									// background color... 
	GifScreen.AspectRatio =	(UCHAR)buf[6]; 
 
	// read colormaps 
	if( BitSet((UCHAR)buf[4], LOCALCOLORMAP) )  
	{ 
		if( !ReadColorMap(fd, GifScreen.BitPixel, GifScreen.ColorMap) )  
		{ 
			m_GIFErrorText = "Error reading GIF colormap"; 
			fclose(fd); 
			return NULL;                                              
		} 
	} 
 
	// non-square pixels, so what?	 
	if( (GifScreen.AspectRatio!=0 ) && (GifScreen.AspectRatio!=49) ) 
	{ 
		m_GIFErrorText = "Non-square pixels in GIF image.\nIgnoring that fact..."; 
	} 
 
	// there can be multiple images in a GIF file... uh? 
	// what the hell do we do with multiple images? 
	// so, we'll be interested in just the first image, cause we're lazy 
 
	for(;;)  
	{	 
		// read a byte; 
		if (!ReadOK(fd,&c,1))  
		{ 
			m_GIFErrorText="Unexpected EOF in GIF.\nGiving up"; 
			fclose(fd); 
			return NULL;  
		} 
	 
		// image terminator 
		if (c==';')  
		{ 
		} 
	 
		if (c=='!')  
		{ 
			if (!ReadOK(fd,&c,1))  
			{ 
				m_GIFErrorText="Error on extension read.\nGiving up"; 
				fclose(fd); 
				return NULL;        
			} 
			DoExtension(fd,c); 
			continue; 
		} 
	 
		if (c!=',')  
		{ 
			// Ignoring c 
			continue; 
		} 
	 
		// read image header 
		if (!ReadOK(fd,buf,9))  
		{ 
			m_GIFErrorText="Error on dimension read\nGiving up"; 
			fclose(fd); 
			return NULL;                      
		} 
	 
		useGlobalColormap=!BitSet((UCHAR)buf[8],LOCALCOLORMAP); 
	 
		bitPixel=1<<(((UCHAR)buf[8]&0x07)+1); 
	 
	    // let's see if we have enough mem to continue? 
 
		long bufsize; 
 
		if ((int)buf[5]>4)  
		{ 
			//AfxMessageBox("This GIF file claims to be > 2000 bytes wide!",MB_OK | MB_ICONINFORMATION); 
		} 
		if ((int)buf[7]>4) 
		{ 
			//AfxMessageBox("This GIF file claims to be > 2000 bytes high!",MB_OK | MB_ICONINFORMATION); 
		}		                                                        
		 
		w=LM_to_uint((UCHAR)buf[4],(UCHAR)buf[5]);		 
		h=LM_to_uint((UCHAR)buf[6],(UCHAR)buf[7]); 
		 
		if ((w<0) || (h<0)) 
		{ 
			m_GIFErrorText="Negative image dimensions!\nGiving up"; 
			fclose(fd); 
			return NULL; 
		} 
				 
		bufsize=(long)w*(long)h; 
		bufsize*=3; 
		bigBuf= (BYTE *) new char [bufsize]; 
		 
		if (bigBuf==NULL)  
		{ 
			m_GIFErrorText="Out of Memory in GIFRead"; 
			fclose(fd); 
			return NULL; 
		} 
			 
	 
		if (!useGlobalColormap)  
		{ 
			if (!ReadColorMap(fd,bitPixel,localColorMap))  
			{ 
				m_GIFErrorText="Error reading GIF colormap\nGiving up"; 
				delete [] bigBuf; 
				fclose(fd); 
				return NULL;                      
			} 
	 
		 	//read image 
			if (!ReadImage(fd, bigBuf, w, h, localColorMap, BitSet((UCHAR)buf[8],INTERLACE)))  
			{ 
				m_GIFErrorText="Error reading GIF file\nLocalColorMap\nGiving up"; 
				delete [] bigBuf; 
				fclose(fd); 
				return NULL; 				 
			} 
		} else 
		{ 
			if (!ReadImage(fd, bigBuf, w, h, GifScreen.ColorMap, BitSet((UCHAR)buf[8],INTERLACE)))  
			{ 
				m_GIFErrorText="Error reading GIF file\nGIFScreen Colormap\nGiving up"; 
				delete [] bigBuf; 
				fclose(fd); 
				return NULL; 			 
			} 
		} 
		break; 
	} 
 
	*width  = w; 
	*height = h; 
		 
	fclose(fd); 
	return bigBuf; 
} 
 
static int ReadColorMap(FILE *fd, int number, UCHAR buffer[3][MAXCOLORMAPSIZE]) 
{ 
	int 	i; 
	UCHAR rgb[3]; 
	 
	for (i=0;i < number; ++i) 
	{ 
		if (!ReadOK(fd,rgb,sizeof(rgb)))  
		{ 
			return FALSE; 
		} 
		 
		buffer[CM_RED][i]=rgb[0]; 
		buffer[CM_GREEN][i]=rgb[1]; 
		buffer[CM_BLUE][i]=rgb[2]; 
	}	 
	return TRUE; 
} 
 
static int DoExtension(FILE *fd, int label) 
{ 
	static char buf[256]; 
	char	*str; 
 
	switch(label)  
	{ 
	case 0x01  : 
		str="Plain Text Ext"; 
		break; 
	case 0xff : 
		str= "Appl ext"; 
		break; 
	case 0xfe : 
		str="Comment Ext"; 
		while (GetDataBlock(fd,(UCHAR *)buf)!=0)  
		{ 
			//AfxMessageBox(buf, MB_OK | MB_ICONINFORMATION); 
		} 
		return FALSE; 
		break; 
	case 0XF9 : 
		str="Graphic Ctrl Ext"; 
		(void)GetDataBlock(fd,(UCHAR *)buf); 
		Gif89.disposal	=(buf[0]>>2)		&0x7; 
		Gif89.inputFlag	=(buf[0]>>1)		&0x1; 
		Gif89.delayTime	=LM_to_uint(buf[1],buf[2]); 
		if ((buf[0]&0x1)!=0) 
			Gif89.transparent=buf[3]; 
	 
		while (GetDataBlock(fd,(UCHAR *)buf)!=0); 
		return FALSE; 
		break; 
	default : 
		str=buf; 
		sprintf(buf,"UNKNOWN (0x%02x)",label); 
		break; 
	} 
	 
	while (GetDataBlock(fd,(UCHAR *)buf)!=0); 
 
	return FALSE; 
} 
 
int ZeroDataBlock=FALSE; 
static int GetDataBlock(FILE *fd, UCHAR *buf) 
{ 
	UCHAR count; 
 
	if (!ReadOK(fd,&count,1)) 
	{ 
		//m_GIFErrorText="Error in GIF DataBlock Size"; 
		return -1; 
	} 
 
	ZeroDataBlock=count==0; 
 
	if ((count!=0) && (!ReadOK(fd,buf,count)))  
	{ 
		//m_GIFErrorText="Error reading GIF datablock"; 
		return -1; 
	} 
	return count; 
} 
 
static int GetCode(FILE *fd, int code_size, int flag) 
{ 
	static UCHAR buf[280]; 
	static int curbit, lastbit, done, last_byte; 
	int i,j,ret; 
	UCHAR count; 
 
	if (flag)  
	{ 
		curbit=0; 
		lastbit=0; 
		done=FALSE; 
		return 0; 
	} 
 
	if ((curbit+code_size) >=lastbit)  
	{ 
		if (done)  
		{ 
			if (curbit >=lastbit)  
			{ 
				//m_GIFErrorText="Ran off the end of my bits"; 
				return 0; 
			} 
			return -1; 
		} 
		buf[0]=buf[last_byte-2];	 
		buf[1]=buf[last_byte-1]; 
 
		if ((count=GetDataBlock(fd,&buf[2]))==0) 
			done=TRUE; 
 
		last_byte=2+count; 
 
		curbit=(curbit - lastbit) + 16; 
 
		lastbit = (2+count)*8; 
	} 
	ret=0; 
	for (i=curbit,j=0; j stack) 
		return *--sp; 
 
	while ((code= GetCode(fd,code_size,FALSE)) >=0) 
	{ 
		if (code==clear_code)  
		{ 
			for (i=0;i0); 
 
			if (count!=0) 
				//AfxMessageBox("Missing EOD in GIF data stream (common occurrence)",MB_OK); 
			return -2;	 
		} 
 
		incode = code; 
 
		if (code >= max_code) 
		{ 
			*sp++=firstcode; 
			code=oldcode; 
		} 
 
		while (code >=clear_code)  
		{ 
			*sp++=vals[code]; 
			if (code==(int)next[code]) 
			{ 
				//m_GIFErrorText="Circular table entry, big GIF Error!"; 
				return -1; 
			} 
			code=next[code]; 
		} 
 
		*sp++ = firstcode=vals[code]; 
 
		if ((code=max_code) <(1<=max_code_size) && 
				(max_code_size < (1< stack) 
			return *--sp; 
	} 
	return code; 
}    
 
static BOOL ReadImage(	FILE *fd, 
						BYTE  * bigMemBuf, 
						int width, int height, 
						UCHAR cmap[3][MAXCOLORMAPSIZE], 
						int interlace) 
{ 
	UCHAR c; 
	int color; 
	int xpos=0, ypos=0, pass=0; 
	long curidx; 
 
	if (!ReadOK(fd,& c,1)) 
	{ 
		return FALSE; 
	} 
 
	if (LZWReadByte(fd,TRUE,c)<0)  
	{ 
		return FALSE; 
	} 
	 
	while ((color = LZWReadByte(fd, FALSE, c)) >= 0 )  
	{ 
        curidx=(long)xpos + (long)ypos * (long)width; 
        curidx*=3; 
         
		*(bigMemBuf+curidx)   = cmap[0][color]; 
		*(bigMemBuf+curidx+1) = cmap[1][color]; 
		*(bigMemBuf+curidx+2) = cmap[2][color];				 
 
		++xpos; 
		if (xpos==width)  
		{ 
			xpos=0; 
			if (interlace) 
			{ 
				switch (pass)  
				{ 
				case 0: 
				case 1: 
					ypos += 8; break; 
				case 2: 
					ypos += 4; break; 
				case 3: 
					ypos += 2; break; 
				} 
 
				if (ypos>=height)  
				{ 
					++pass; 
					switch (pass) 
					{ 
					case 1: ypos = 4; break; 
					case 2: ypos = 2; break; 
					case 3: ypos = 1; break; 
					default : goto fini; 
					} 
				} 
			}  
			else  
			{ 
				++ypos; 
			} 
		} 
		if (ypos >=height) 
			break; 
	} 
fini : 
	if (LZWReadByte(fd,FALSE,c)>=0)  
	{ 
	} 
	return TRUE; 
} 
//	gets image dimensions 
//	returns -1,-1 on bad read 
void GIFFile::GIFGetDimensions(CString path, UINT *width, UINT *height) 
{ 
	UCHAR			buf[16]; 
	UCHAR			c; 
	char			version[4]; 
	FILE 			*fd;           
	int 			w=0; 
	int				h=0;	 
	 
	if (_access(path,0)!=0)  
	{ 
		*width=(UINT)-1;*height=(UINT)-1; 
		return; 
	} 
	 
	fd=fopen(path,"rb"); 
	if (fd==NULL)  
	{                        
		*width=(UINT)-1;*height=(UINT)-1; 
		return; 
	} 
 
	// read GIF file header 
	if (!ReadOK(fd,buf,6)) 
		goto bail; 
 
	// need the string "GIF" in the header 
	if (strncmp((char *)buf,"GIF",3)!=0) 
		goto bail; 
 
	strncpy(version,(char *)(buf+3),3); 
	version[3]='\0'; 
 
	// only handle v 87a and 89a 
	if ((strcmp(version,"87a")!=0)&&(strcmp(version,"89a")!=0)) 
		goto bail; 
 
	// screen description 
	if (!ReadOK(fd,buf,7)) 
		goto bail; 
 
	GifScreen.Width		=	LM_to_uint((UCHAR)buf[0],(UCHAR)buf[1]); 
	GifScreen.Height	=	LM_to_uint((UCHAR)buf[2],(UCHAR)buf[3]); 
	GifScreen.BitPixel	=	2<<((UCHAR)buf[4]&0x07); 
	GifScreen.ColorResolution=((((UCHAR)buf[4]&0x70)>>3)+1); 
	GifScreen.BackGround=	(UCHAR)buf[5];									// background color... 
	GifScreen.AspectRatio=	(UCHAR)buf[6]; 
             
	*width  = GifScreen.Width;		 
	*height = GifScreen.Height; 
 
	// read colormaps 
	if (BitSet((UCHAR)buf[4],LOCALCOLORMAP)) 
		if (!ReadColorMap(fd,GifScreen.BitPixel,GifScreen.ColorMap)) 
			goto bail;                                          
  
	if (!ReadOK(fd,&c,1)) 
		goto bail; 
 
	if (c!=',') 
		goto bail; 
 
	// read image header 
	if (!ReadOK(fd,buf,9)) 
		goto bail;                     
	 
	//*width=LM_to_uint((UCHAR)buf[4],(UCHAR)buf[5]);		 
	//*height=LM_to_uint((UCHAR)buf[6],(UCHAR)buf[7]); 
		 
	if ((*width<0) || (*height<0)) 
		goto bail; 
 
	// good 
	fclose(fd); 
	return; 
 
bail:       
	// bad 
	fclose(fd); 
	//*width=(UINT)-1;*height=(UINT)-1; 
	return; 
} 
 
//////////////////////////////////////////////////////////////////////// 
// 
//	This is the writing portion of the GIFFile class. 
//	It is based on code from Programming for Graphics Files	by John Levine 
// 
//	This is free to use and modify provided proper credit is given 
// 
//	This writes 256 color GIFs version GIF87a. 
// 
//	see GIFFile.h for example 
//////////////////////////////////////////////////////////////////////// 
//////////// 
// 
//	GIF writing section 
// 
//////////// 
 
// a code_int must be able to hold 2**BITS values of type int, and also -1 
static int 				Width, Height; 
static int				curx, cury; 
static long 			CountDown; 
static unsigned long	cur_accum = 0; 
static int				cur_bits = 0; 
static unsigned char	*buffer; 
 
 
/* 
 * Bump the 'curx' and 'cury' to point to the next pixel 
 */ 
void GIFFile::BumpPixel() 
{ 
    /* 
     * Bump the current X position 
     */ 
    ++curx; 
 
    if( curx == Width ) 
	{ 
        curx = 0; 
		++cury; 
    } 
} 
 
/******************************************************************************* 
* Return the next pixel from the image 
*******************************************************************************/ 
 
int GIFFile::GIFNextPixel( ) 
{ 
    unsigned long index; 
    int r; 
     
    if( CountDown == 0 ) 
        return EOF; 
 
    --CountDown; 
     
    index= (unsigned long)curx + (unsigned long)cury * (unsigned long)Width; 
     
	r = *(buffer+index); 
 
    BumpPixel(); 
 
    return r; 
} 
 
/******************************************************************************* 
*	here's the entry point.  
*	file ptr, screen width, height, background color, bits per pixel and 
*	arrays of color values (0-255) 
*******************************************************************************/ 
BOOL GIFFile::GIFWriteFileFrom256Color(unsigned char  * buf, 
							CString name, 
							int GWidth,  
							int GHeight, 
							int BackGround, 
							int Red[], int Green[], int Blue[]) 
{                        
	FILE *fp; 
	int B; 
	int RWidth, RHeight; 
	int LeftOfs, TopOfs; 
	int Resolution; 
	int ColorMapSize; 
	int InitCodeSize; 
	int i; 
	int BitsPerPixel = 8; 
 
	fp=fopen(name,"wb"); 
	if (fp==NULL) 
	{ 
		m_GIFErrorText="Can't open GIF for writing"; 
		return FALSE; 
	} 
	 
	ColorMapSize = 1 << BitsPerPixel; 
 
	buffer=buf; 
 
	RWidth = Width = GWidth; 
	RHeight = Height = GHeight; 
	LeftOfs = TopOfs = 0; 
 
	cur_accum = 0; 
	cur_bits = 0; 
 
	Resolution = BitsPerPixel; 
 
	CountDown = (long)Width * (long) Height; 
 
	if (BitsPerPixel <=1) 
	InitCodeSize=2; 
	else 
	InitCodeSize = BitsPerPixel; 
 
	curx = cury =0; 
 
	fwrite("GIF87a",1,6,fp); 
 
	Putword(RWidth,fp); 
	Putword(RHeight,fp); 
 
	B=0x80; 
	 
	B |=(Resolution -1) << 5; 
 
	B |=(BitsPerPixel - 1); 
 
	fputc(B,fp); 
 
	fputc(BackGround,fp); 
	 
	fputc(0,fp); 
 
	for(i=0; i 0 ) 
            goto probe; 
nomatch: 
        output ( (code_int) ent ); 
        ent = c; 
        if ( free_ent < maxmaxcode )  
		{	/* } */ 
            CodeTabOf (i) = free_ent++; /* code -> hashtable */ 
            HashTabOf (i) = fcode; 
        } else 
                cl_block(); 
    } 
    /* 
     * Put out the final code. 
     */ 
    output( (code_int)ent ); 
    output( (code_int) EOFCode ); 
} 
 
/***************************************************************** 
 * TAG( output ) 
 * 
 * Output the given code. 
 * Inputs: 
 *      code:   A n_bits-bit integer.  If == -1, then EOF.  This assumes 
 *              that n_bits =< (long)wordsize - 1. 
 * Outputs: 
 *      Outputs code to the file. 
 * Assumptions: 
 *      Chars are 8 bits long. 
 * Algorithm: 
 *      Maintain a BITS character long buffer (so that 8 codes will 
 * fit in it exactly).  Use the VAX insv instruction to insert each 
 * code in turn.  When the buffer fills up empty it and start over. 
 */ 
 
static unsigned long masks[] = { 0x0000, 0x0001, 0x0003, 0x0007, 0x000F, 
                                  0x001F, 0x003F, 0x007F, 0x00FF, 
                                  0x01FF, 0x03FF, 0x07FF, 0x0FFF, 
                                  0x1FFF, 0x3FFF, 0x7FFF, 0xFFFF }; 
 
void GIFFile::output( code_int  code) 
{ 
    cur_accum &= masks[ cur_bits ]; 
 
    if( cur_bits > 0 ) 
        cur_accum |= ((long)code << cur_bits); 
    else 
        cur_accum = code; 
 
    cur_bits += n_bits; 
 
    while( cur_bits >= 8 )  
	{ 
        char_out( (unsigned int)(cur_accum & 0xff) ); 
        cur_accum >>= 8; 
        cur_bits -= 8; 
    } 
 
    /* 
     * If the next entry is going to be too big for the code size, 
     * then increase it, if possible. 
     */ 
   if ( free_ent > maxcode || clear_flg )  
   { 
        if( clear_flg ) { 
            maxcode = MAXCODE (n_bits = g_init_bits); 
            clear_flg = 0; 
        }  
		else 
		{ 
            ++n_bits; 
            if ( n_bits == maxbits ) 
                maxcode = maxmaxcode; 
            else 
                maxcode = MAXCODE(n_bits); 
        } 
    } 
	 
	if( code == EOFCode )  
	{ 
        /* 
         * At EOF, write the rest of the buffer. 
         */ 
        while( cur_bits > 0 ) { 
            char_out( (unsigned int)(cur_accum & 0xff) ); 
            cur_accum >>= 8; 
            cur_bits -= 8; 
        } 
	 
        flush_char(); 
	 
        fflush( g_outfile ); 
	 
        if( ferror( g_outfile ) )  
		{ 
			AfxMessageBox("Write Error in GIF file",MB_OK); 
		} 
    } 
} 
 
void GIFFile::cl_block() 
{ 
	cl_hash((count_int)HSIZE); 
	free_ent=ClearCode+2; 
	clear_flg=1; 
 
	output((code_int)ClearCode); 
} 
 
void GIFFile::cl_hash(register count_int hsize) 
 
{ 
	register count_int *htab_p = htab+hsize; 
 
	register long i; 
	register long m1 = -1L; 
 
	i = hsize - 16; 
 
	do { 
		*(htab_p-16)=m1; 
		*(htab_p-15)=m1; 
		*(htab_p-14)=m1; 
		*(htab_p-13)=m1; 
		*(htab_p-12)=m1; 
		*(htab_p-11)=m1; 
		*(htab_p-10)=m1; 
		*(htab_p-9)=m1; 
		*(htab_p-8)=m1; 
		*(htab_p-7)=m1; 
		*(htab_p-6)=m1; 
		*(htab_p-5)=m1; 
		*(htab_p-4)=m1; 
		*(htab_p-3)=m1; 
		*(htab_p-2)=m1; 
		*(htab_p-1)=m1; 
		 
		htab_p-=16; 
	} while ((i-=16) >=0); 
 
	for (i+=16;i>0;--i) 
		*--htab_p=m1; 
} 
 
/******************************************************************************* 
*	GIF specific 
*******************************************************************************/ 
 
static int a_count; 
 
void GIFFile::char_init() 
{ 
	a_count=0; 
} 
 
static char accum[256]; 
 
void GIFFile::char_out(int c) 
{ 
	accum[a_count++]=c; 
	if (a_count >=254) 
		flush_char(); 
} 
 
void GIFFile::flush_char() 
{ 
	if (a_count > 0)  
	{ 
		fputc(a_count,g_outfile); 
		fwrite(accum,1,a_count,g_outfile); 
		a_count=0; 
	} 
} 
BYTE * MakeColormappedGrayscale(BYTE *inBuf, 
								UINT inWidth, 
								UINT inHeight, 
								UINT inWidthBytes, 
								UINT colors, 
								RGBQUAD* colormap) 
{ 
	////////////////////////////////////////////////////////////////////////	 
	// allocate a buffer to colormap 
	BYTE *tmp = (BYTE *)  new BYTE[inWidth * inHeight]; 
	if (tmp==NULL) 
		return NULL; 
 
	// force our image to use a stupid gray scale 
	UINT color; 
	for (color = 0;color < colors; color++) { 
		colormap[color].rgbRed = color * 256 / colors; 
		colormap[color].rgbGreen = color * 256 / colors; 
		colormap[color].rgbBlue = color * 256 / colors; 
	} 
 
 
	UINT col, row; 
	for (row =0; row < inHeight; row++) { 
 
		for (col=0;col dwDataLen  = iFile->GetLength();  
    lpPCXDVar->dwDataLen -= sizeof(PCXHEADER); 
    lpPCXDVar->dwDataLen -= ( (lpPCXDVar->wNewBits==8) ? 769 : 0 ); 
    iFile->Seek(sizeof(PCXHEADER),CFile::begin); 
 
    lpPCXDVar->wMemLen    = lpPCXDVar->dwDataLen; 
    lpPCXDVar->lpDataBuff = new BYTE[lpPCXDVar->wMemLen]; 
	iFile->ReadHuge(lpPCXDVar->lpDataBuff,lpPCXDVar->wMemLen); 
 
    lpPCXDVar->lpBgnBuff  = lpPCXDVar->lpDataBuff; 
    lpPCXDVar->lpEndBuff  = lpPCXDVar->lpBgnBuff + lpPCXDVar->wMemLen; 
    lpTemp                = new BYTE[wWidthBytes]; 
 
    for(wi=0;wiwDepth;wi++) 
    { 
		lpImage    = iTempFile + (lpPCXDVar->wDepth -1 -wi) * wWidthBytes; 
		lpImageBgn = lpImage; 
 
        iDecodeLine(lpPCXDVar,lpTemp); 
        switch(lpPCXDVar->wNewBits) 
		{ 
			case  1: 
            case  8: 
			{ 
				memcpy(lpImage,lpTemp,lpPCXDVar->wLineBytes); 
				break; 
			}  
            case  4: 
			{ 
                lpImage  = lpImageBgn; 
                lpPlane0 = lpTemp; 
                lpPlane1 = lpPlane0 + lpPCXDVar->wLineBytes; 
                lpPlane2 = lpPlane1 + lpPCXDVar->wLineBytes; 
                lpPlane3 = lpPlane2 + lpPCXDVar->wLineBytes; 
                for(wj=0;wjwLineBytes;wj++) 
				{ 
                    byPlane0   = *lpPlane0++; 
                    byPlane1   = *lpPlane1++; 
                    byPlane2   = *lpPlane2++; 
                    byPlane3   = *lpPlane3++; 
 
                    byTemp     = 0x00; 
                    byTemp    |= ( (byPlane3 & 0x80) ? 0x80 : byTemp ); 
                    byTemp    |= ( (byPlane2 & 0x80) ? 0x40 : byTemp ); 
                    byTemp    |= ( (byPlane1 & 0x80) ? 0x20 : byTemp ); 
                    byTemp    |= ( (byPlane0 & 0x80) ? 0x10 : byTemp ); 
                    byTemp    |= ( (byPlane3 & 0x40) ? 0x08 : byTemp ); 
                    byTemp    |= ( (byPlane2 & 0x40) ? 0x04 : byTemp ); 
                    byTemp    |= ( (byPlane1 & 0x40) ? 0x02 : byTemp ); 
                    byTemp    |= ( (byPlane0 & 0x40) ? 0x01 : byTemp ); 
                   *lpImage++ = byTemp; 
 
                    byTemp     = 0x00; 
                    byTemp    |= ( (byPlane3 & 0x20) ? 0x80 : byTemp ); 
                    byTemp    |= ( (byPlane2 & 0x20) ? 0x40 : byTemp ); 
                    byTemp    |= ( (byPlane1 & 0x20) ? 0x20 : byTemp ); 
                    byTemp    |= ( (byPlane0 & 0x20) ? 0x10 : byTemp ); 
                    byTemp    |= ( (byPlane3 & 0x10) ? 0x08 : byTemp ); 
                    byTemp    |= ( (byPlane2 & 0x10) ? 0x04 : byTemp ); 
                    byTemp    |= ( (byPlane1 & 0x10) ? 0x02 : byTemp ); 
                    byTemp    |= ( (byPlane0 & 0x10) ? 0x01 : byTemp ); 
                   *lpImage++ = byTemp; 
 
                    byTemp     = (BYTE)0x00; 
                    byTemp    |= ( (byPlane3 & 0x08) ? 0x80 : byTemp ); 
                    byTemp    |= ( (byPlane2 & 0x08) ? 0x40 : byTemp ); 
                    byTemp    |= ( (byPlane1 & 0x08) ? 0x20 : byTemp ); 
                    byTemp    |= ( (byPlane0 & 0x08) ? 0x10 : byTemp ); 
                    byTemp    |= ( (byPlane3 & 0x04) ? 0x08 : byTemp ); 
                    byTemp    |= ( (byPlane2 & 0x04) ? 0x04 : byTemp ); 
                    byTemp    |= ( (byPlane1 & 0x04) ? 0x02 : byTemp ); 
                    byTemp    |= ( (byPlane0 & 0x04) ? 0x01 : byTemp ); 
                   *lpImage++ = byTemp; 
 
                    byTemp     = 0x00; 
                    byTemp    |= ( (byPlane3 & 0x02) ? 0x80 : byTemp ); 
                    byTemp    |= ( (byPlane2 & 0x02) ? 0x40 : byTemp ); 
                    byTemp    |= ( (byPlane1 & 0x02) ? 0x20 : byTemp ); 
                    byTemp    |= ( (byPlane0 & 0x02) ? 0x10 : byTemp ); 
                    byTemp    |= ( (byPlane3 & 0x01) ? 0x08 : byTemp ); 
                    byTemp    |= ( (byPlane2 & 0x01) ? 0x04 : byTemp ); 
                    byTemp    |= ( (byPlane1 & 0x01) ? 0x02 : byTemp ); 
                    byTemp    |= ( (byPlane0 & 0x01) ? 0x01 : byTemp ); 
                   *lpImage++ = byTemp; 
				} 
                break; 
			} 
            case 24: 
			{ 
				lpPlane0 = lpTemp; 
                lpPlane1 = lpPlane0 + lpPCXDVar->wLineBytes; 
                lpPlane2 = lpPlane1 + lpPCXDVar->wLineBytes; 
                for(wj=0;wjwLineBytes;wj++) 
				{ 
                   *lpImage++ = *lpPlane2++; 
                   *lpImage++ = *lpPlane1++; 
                   *lpImage++ = *lpPlane0++; 
				}  
                break; 
			}   
		}        
    }  
 
	if(lpTemp!=NULL) delete lpTemp; 
    if(lpPCXDVar->lpDataBuff!=NULL) delete lpPCXDVar->lpDataBuff; 
	lpPCXDVar->lpDataBuff = lpTemp = NULL; 
	return 0; 
} 
 
void iDecodeLine(LPPCXD_VAR lpPCXDVar,BYTE* lpTemp) 
{ 
   BYTE* lpTempEnd; 
   WORD  wi; 
   BYTE  byChar; 
   int   iCount; 
   //int   iReturn; 
 
   for(wi=0;wiwPlanes;wi++) 
   { 
	   lpTempEnd = lpTemp + lpPCXDVar->wLineBytes; 
       while( lpTemplpBgnBuff++; 
            
           if ( (byChar & 0xC0) == 0xC0 ) 
		   { 
               iCount = (int)(byChar & 0x3F); 
               byChar = *lpPCXDVar->lpBgnBuff++; 
               
               while( iCount-- ) 
			   { 
				   *lpTemp++ = byChar; 
			   } 
		   }   
           else 
		   { 
               *lpTemp++ = byChar; 
		   } 
	   } 
   }  
} 
 
 
BOOL WritePcxImage(CFile * OutFile,BYTE *iTempFile,LPPCXC_VAR lpPCXCVar,long wWidthBytes) 
{ 
   BYTE*  lpImage; 
   BYTE*  lpTemp; 
   BYTE*  lpImageBgn; 
   BYTE*  lpPlane0; 
   BYTE*  lpPlane1; 
   BYTE*  lpPlane2; 
   BYTE*  lpPlane3; 
   WORD   wi; 
   WORD   wj; 
   BYTE   byTemp; 
   BYTE   byPlane0; 
   BYTE   byPlane1; 
   BYTE   byPlane2; 
   BYTE   byPlane3;    
 
   lpPCXCVar->lpDataBuff = new BYTE[MAX_BUFF_SIZE]; 
   lpPCXCVar->lpEndBuff  = lpPCXCVar->lpDataBuff; 
   lpPCXCVar->wByteCnt   = 0; 
   lpTemp                = new BYTE[wWidthBytes]; 
 
   for(wi=0;wiwDepth;wi++) 
   { 
      lpImage    = iTempFile + (lpPCXCVar->wDepth -1 -wi) * wWidthBytes; 
	  lpImageBgn = lpImage; 
 
      switch(lpPCXCVar->wBits) 
      { 
         case  1: 
         case  8: 
         { 
            memcpy(lpTemp,lpImage,lpPCXCVar->wLineBytes); 
            break; 
         } 
         case  4: 
         { 
            lpPlane0 = lpTemp; 
            lpPlane1 = lpPlane0 + lpPCXCVar->wLineBytes; 
            lpPlane2 = lpPlane1 + lpPCXCVar->wLineBytes; 
            lpPlane3 = lpPlane2 + lpPCXCVar->wLineBytes; 
            for(wj=0;wjwLineBytes;wj++) 
            { 
               byPlane0    = 0x00; 
               byPlane1    = 0x00; 
               byPlane2    = 0x00; 
               byPlane3    = 0x00; 
 
               byTemp      = *lpImage++; 
               byPlane3   |= ( (byTemp & 0x80) ? 0x80 : byPlane3 ); 
               byPlane2   |= ( (byTemp & 0x40) ? 0x80 : byPlane2 ); 
               byPlane1   |= ( (byTemp & 0x20) ? 0x80 : byPlane1 ); 
               byPlane0   |= ( (byTemp & 0x10) ? 0x80 : byPlane0 ); 
               byPlane3   |= ( (byTemp & 0x08) ? 0x40 : byPlane3 ); 
               byPlane2   |= ( (byTemp & 0x04) ? 0x40 : byPlane2 ); 
               byPlane1   |= ( (byTemp & 0x02) ? 0x40 : byPlane1 ); 
               byPlane0   |= ( (byTemp & 0x01) ? 0x40 : byPlane0 ); 
 
               byTemp      = *lpImage++; 
               byPlane3   |= ( (byTemp & 0x80) ? 0x20 : byPlane3 ); 
               byPlane2   |= ( (byTemp & 0x40) ? 0x20 : byPlane2 ); 
               byPlane1   |= ( (byTemp & 0x20) ? 0x20 : byPlane1 ); 
               byPlane0   |= ( (byTemp & 0x10) ? 0x20 : byPlane0 ); 
               byPlane3   |= ( (byTemp & 0x08) ? 0x10 : byPlane3 ); 
               byPlane2   |= ( (byTemp & 0x04) ? 0x10 : byPlane2 ); 
               byPlane1   |= ( (byTemp & 0x02) ? 0x10 : byPlane1 ); 
               byPlane0   |= ( (byTemp & 0x01) ? 0x10 : byPlane0 ); 
 
               byTemp      = *lpImage++; 
               byPlane3   |= ( (byTemp & 0x80) ? 0x08 : byPlane3 ); 
               byPlane2   |= ( (byTemp & 0x40) ? 0x08 : byPlane2 ); 
               byPlane1   |= ( (byTemp & 0x20) ? 0x08 : byPlane1 ); 
               byPlane0   |= ( (byTemp & 0x10) ? 0x08 : byPlane0 ); 
               byPlane3   |= ( (byTemp & 0x08) ? 0x04 : byPlane3 ); 
               byPlane2   |= ( (byTemp & 0x04) ? 0x04 : byPlane2 ); 
               byPlane1   |= ( (byTemp & 0x02) ? 0x04 : byPlane1 ); 
               byPlane0   |= ( (byTemp & 0x01) ? 0x04 : byPlane0 ); 
 
               byTemp      = *lpImage++; 
               byPlane3   |= ( (byTemp & 0x80) ? 0x02 : byPlane3 ); 
               byPlane2   |= ( (byTemp & 0x40) ? 0x02 : byPlane2 ); 
               byPlane1   |= ( (byTemp & 0x20) ? 0x02 : byPlane1 ); 
               byPlane0   |= ( (byTemp & 0x10) ? 0x02 : byPlane0 ); 
               byPlane3   |= ( (byTemp & 0x08) ? 0x01 : byPlane3 ); 
               byPlane2   |= ( (byTemp & 0x04) ? 0x01 : byPlane2 ); 
               byPlane1   |= ( (byTemp & 0x02) ? 0x01 : byPlane1 ); 
               byPlane0   |= ( (byTemp & 0x01) ? 0x01 : byPlane0 ); 
 
               *lpPlane0++ = byPlane0; 
               *lpPlane1++ = byPlane1; 
               *lpPlane2++ = byPlane2; 
               *lpPlane3++ = byPlane3; 
            } 
            break; 
         } 
         case 24: 
         { 
            lpPlane0 = lpTemp; 
            lpPlane1 = lpPlane0 + lpPCXCVar->wLineBytes; 
            lpPlane2 = lpPlane1 + lpPCXCVar->wLineBytes; 
            for(wj=0;wjwLineBytes;wj++) 
            { 
               *lpPlane2++ = *lpImage++; 
               *lpPlane1++ = *lpImage++; 
               *lpPlane0++ = *lpImage++; 
            } 
            break; 
         } 
      } 
      iEncodeLine(OutFile,lpPCXCVar,lpTemp); 
   } 
 
   if(lpPCXCVar->wByteCnt ) 
   { 
       OutFile->Write(lpPCXCVar->lpDataBuff,lpPCXCVar->wByteCnt); 
   } 
   if(lpTemp!=NULL) delete lpTemp; 
   if(lpPCXCVar->lpDataBuff!=NULL) delete lpPCXCVar->lpDataBuff; 
   lpPCXCVar->lpDataBuff = lpTemp = NULL; 
   return TRUE; 
} 
void iEncodeLine(CFile * ExportFile,LPPCXC_VAR lpPCXCVar,BYTE* lpTemp) 
{ 
	BYTE* lpTempEnd; 
    WORD  wi; 
    int   iCount; 
 
    for(wi=0;wiwPlanes;wi++) 
    { 
		lpTempEnd = lpTemp + lpPCXCVar->wLineBytes; 
        while( lpTemp1 ) 
			{ 
               *lpPCXCVar->lpEndBuff++ = (BYTE)(iCount | 0xC0); 
                lpPCXCVar->wByteCnt    ++; 
                if ( lpPCXCVar->wByteCnt==MAX_BUFF_SIZE ) 
				{ 
                    ExportFile->Write(lpPCXCVar->lpDataBuff,lpPCXCVar->wByteCnt); 
                    lpPCXCVar->wByteCnt  = 0; 
                    lpPCXCVar->lpEndBuff = lpPCXCVar->lpDataBuff; 
				} 
			} 
            else 
			{ 
				if ( (*lpTemp & 0xC0) == 0xC0 ) 
				{ 
				   *lpPCXCVar->lpEndBuff++ = 0xC1; 
                    lpPCXCVar->wByteCnt    ++; 
                    if ( lpPCXCVar->wByteCnt==MAX_BUFF_SIZE ) 
					{ 
                        ExportFile->Write(lpPCXCVar->lpDataBuff,lpPCXCVar->wByteCnt); 
					    lpPCXCVar->wByteCnt  = 0; 
					    lpPCXCVar->lpEndBuff = lpPCXCVar->lpDataBuff; 
					} 
				} 
			} 
           *lpPCXCVar->lpEndBuff++ = *lpTemp++; 
            lpPCXCVar->wByteCnt    ++; 
            if ( lpPCXCVar->wByteCnt==MAX_BUFF_SIZE ) 
			{ 
                ExportFile->Write(lpPCXCVar->lpDataBuff,lpPCXCVar->wByteCnt); 
                lpPCXCVar->wByteCnt  = 0; 
                lpPCXCVar->lpEndBuff = lpPCXCVar->lpDataBuff; 
			} 
		} 
	} 
}