⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 giffile.cpp

📁 医学图象处理系统
💻 CPP
📖 第 1 页 / 共 3 页
字号:
////////////////////////////////////////////////////////////
//	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 <io.h>
#include <fcntl.h>
#include <string.h>
#include <stdio.h>
#include <conio.h>
#include <stdlib.h>
#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<code_size;++i,++j)
		ret|=((buf[i/8]&(1<<(i% 8)))!=0)<<j;

	curbit+=code_size;

	return ret;
}

static int LZWReadByte(FILE *fd, int flag, int input_code_size)
{
	static int fresh=FALSE;
	int code, incode;
	static int code_size, set_code_size;
	static int max_code, max_code_size;
	static int firstcode, oldcode;
	static int clear_code, end_code;

	static unsigned short  next[1<<MAX_LZW_BITS];
	static UCHAR  vals[1<<MAX_LZW_BITS];
	static UCHAR  stack [1<<(MAX_LZW_BITS+1)];
	static UCHAR  *sp;
	
	register int i;

	if (flag) 
	{
		set_code_size=input_code_size;
		code_size=set_code_size+1;
		clear_code=1<<set_code_size;
		end_code = clear_code+1;
		max_code = clear_code+2;
		max_code_size=2*clear_code;

		GetCode(fd,0,TRUE);

		fresh=TRUE;
	
		for(i=0;i<clear_code;++i) 
		{
			next[i]=0;
			vals[i]=i;
		}

		for (;i<(1<<MAX_LZW_BITS);++i)
			next[i]=vals[0]=0;
	
		sp=stack;

		return 0;
	}
	else if (fresh) 
	{
			fresh=FALSE;

			do 
			{
				firstcode=oldcode=GetCode(fd,code_size,FALSE);
			} while (firstcode==clear_code);
			return firstcode;
	}  

	if (sp > stack)
		return *--sp;

	while ((code= GetCode(fd,code_size,FALSE)) >=0)
	{
		if (code==clear_code) 
		{
			for (i=0;i<clear_code;++i) 
			{
				next[i]=0;
				vals[i]=i;
			}
			for (;i<(1<<MAX_LZW_BITS);++i)	
				next[i]=vals[i]=0;
			code_size=set_code_size+1;
			max_code_size=2*clear_code;
			max_code=clear_code+2;
			sp=stack;
			firstcode=oldcode=GetCode(fd,code_size,FALSE);
			return firstcode;
		} 
		else if (code==end_code)
		{
			int count;
			UCHAR buf[260];
	
			if (ZeroDataBlock)
				return -2;

			while ((count=GetDataBlock(fd,buf)) >0);

			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_LZW_BITS)) 
		{
			next[code]=oldcode;
			vals[code]=firstcode;
			++max_code;
			if ((max_code >=max_code_size) &&
				(max_code_size < (1<<MAX_LZW_BITS)))
			{
				 max_code_size*=2;
				++code_size;
			}
		}

		oldcode=incode;

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -