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

📄 gif89a.cpp

📁 基于minigui开发的一套图形控件系统
💻 CPP
📖 第 1 页 / 共 2 页
字号:
/***************************************

*

*

*

*

*********************************************/

#include <fstream.h>

#include <string.h>

#include <stdlib.h>

#include "gif89a.h"

#include <minigui/common.h>



#define MAX_LWZ_BITS            12



CGif89a::CGif89a()

{	

	opened = FALSE;

	error = FALSE;

	ZeroDataBlock = 0;

}



CGif89a::CGif89a(const char* fileName, BOOL inMem)

{	

	opened = FALSE;

	ZeroDataBlock = 0;

	if(open(fileName,inMem))

	{	

		opened = TRUE;

		error = FALSE;

	}

	else

	{	opened = FALSE;

		error = TRUE;

	}

}



CGif89a::~CGif89a()

{	

	close();

}



BOOL CGif89a::operator!()

{	

	return error;

}



BOOL CGif89a::open(const char* fileName, BOOL b)

{	

	char cc[4];

	BYTE be;



	ifs= NULL;

	inMem = b;

	allFrames = NULL;

	curIndex = 0;

	curFrame.pColorTable = NULL;

	curFrame.dataBuf = NULL;

	ctrlExt.active = FALSE;



	fprintf(stderr, "___GIF89a begin open file=%s\n", fileName);

	

	if(opened)

		return FALSE;

	ifs = fopen(fileName,"r");

	if(ifs == NULL)

		return FALSE;

	

	//GIF文件标识

	fread(cc, sizeof(char), 3, ifs);

	cc[3] = 0;

	if(strncmp(cc,"GIF",3) != 0)

		goto error;

	fprintf(stderr, "___GIF89a begin Signature=%s\n", cc);

	

	//GIF文件版本号

	fread(version, sizeof(char), 3, ifs);

	version[3] = 0;

	if(strncmp(version,"89a",3) > 0)//&& (strncmp(version,"87a",3) != 0)

		goto error;

	fprintf(stderr, "___GIF89a begin version=%s\n", version);

	

	//逻辑屏幕宽度

	fread((char*)&gInfo.scrWidth, sizeof(char), 2, ifs);

	fread((char*)&gInfo.scrHeight, sizeof(char), 2, ifs);

	fprintf(stderr, "___GIF89a begin logicwidth=%d, logicheight=%d\n", gInfo.scrWidth, gInfo.scrHeight);

	

	if(ferror(ifs))

		goto error;

	

	fread((char*)&be, sizeof(char), 1, ifs);

	if((be&0x80) != 0)

		gInfo.gFlag = TRUE;

	else

		gInfo.gFlag = FALSE;

	gInfo.colorRes = ((be&0x70)>>4)+1;

	fprintf(stderr, "___GIF89a begin colorRes =%d\n", gInfo.colorRes);

	

	if(gInfo.gFlag)

	{	

		if((be&0x08) != 0)

			gInfo.gSort = TRUE;

		else

			gInfo.gSort = FALSE;

		gInfo.gSize = 1;

		gInfo.gSize <<= ((be&0x07)+1);

	}

	fread((char*)&be, sizeof(char), 1, ifs);

	gInfo.BKColorIdx = be;

	

	fread((char*)&be, sizeof(char), 1, ifs);

	gInfo.pixelAspectRatio = be;

	if(ferror(ifs))

		goto error;

	if(gInfo.gFlag)

	{	

		fread((char*)gColorTable, sizeof(char), gInfo.gSize * 3, ifs);

		gInfo.gColorTable = gColorTable;

	}

	else

		gInfo.gColorTable = NULL;

	

	fprintf(stderr, "___GIF89a begin check frames\n");

	dataStart = ftell(ifs);

	if((gInfo.frames = checkFrames(ifs)) == 0)

		goto error;

	if(inMem)

	{	

		if((allFrames = new FRAME[gInfo.frames]) == NULL)

			goto error;

		memset(allFrames, 0, sizeof(FRAME)*gInfo.frames);

		

		fprintf(stderr, "___GIF89a begin get all frames\n");

		if(!getAllFrames(ifs))

		{	

			delete[] allFrames;

			allFrames = NULL;

			goto error;

		}

		fclose(ifs);

	}

	opened = TRUE;

	return TRUE;

error:

	fclose(ifs);

	return FALSE;

}



UINT CGif89a::checkFrames(FILE* ifs)

{	

	BYTE be;

	BOOL fileEnd = FALSE;

	UINT frames=0;

	long pos;



	fprintf(stderr, "___GIF89a checkframes begin \n");

	pos = ftell(ifs);

	while(!feof(ifs) && !fileEnd)

	{	

		fread((char*)&be,sizeof(char), 1, ifs);

		switch(be)

		{	

			case 0x21:

			{

				fread((char*)&be,sizeof(char), 1, ifs);

				switch(be)

				{	case 0xf9:

					case 0xfe:

					case 0x01:

					case 0xff:

						while(!feof(ifs))

						{	

							fread((char*)&be,sizeof(be), 1, ifs);

							if(be == 0)

								break;

							fseek(ifs, be, SEEK_CUR);

						}

						break;

					default:

						return 0;

				}

				break;

			}

			case 0x2c:

			{	

				BYTE bp;

				BOOL lFlag=FALSE;

				UINT lSize=1;

				

				frames++;

				fseek(ifs, 8, SEEK_CUR);

				fread((char*)&bp, sizeof(char), 1, ifs);

				if((bp&0x80) != 0)

					lFlag = TRUE;

				lSize <<= ((bp&0x07)+1);

				if(lFlag)

					fseek(ifs, lSize*3, SEEK_CUR);

				if(ferror(ifs))

					return 0;

				fread((char*)&be, sizeof(char), 1, ifs);

				while(!feof(ifs))

				{	

					fread((char*)&be,sizeof(be), 1, ifs);

					if(be == 0)

						break;

					fseek(ifs, be, SEEK_CUR);

				}

				break;

			}

			case 0x3b:

				fileEnd = TRUE;

				break;

			case 0x00:

				break;

			default:

				return 0;

		}

	}

	fseek(ifs, pos, SEEK_SET);

	

	fprintf(stderr, "___GIF89a checkframes end \n");

	return frames;

}



int CGif89a::GetDataBlock(FILE *src, unsigned char *buf)

{

    unsigned char count;



    if (!fread(&count, 1, 1, src))

        return 0;

    ZeroDataBlock = count == 0;



    if ((count != 0) && (!fread(buf, count, 1, src)))

        return 0;

    return count;

}





int CGif89a::GetCode(FILE *src, int code_size, int flag)

{

    static unsigned char buf[280];

    static int curbit, lastbit, done, last_byte;

    int i, j, ret;

    unsigned char count;



    if (flag) 

	{

        curbit = 0;

        lastbit = 0;

        done = FALSE;

        return 0;

    }

    if ((curbit + code_size) >= lastbit) 

	{

        if (done) 

		{

            if (curbit >= lastbit)

            	return -1;

        }

        buf[0] = buf[last_byte - 2];

        buf[1] = buf[last_byte - 1];



        if ((count = GetDataBlock(src, &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;

}



int CGif89a::bmpComputePitch (int bpp, Uint32 width, Uint32* pitch, BOOL does_round)

{

    Uint32 linesize;

    int bytespp = 1;



    if(bpp == 1)

        linesize = PIX2BYTES (width);

    else if(bpp <= 4)

        linesize = PIX2BYTES (width << 2);

    else if (bpp <= 8)

        linesize = width;

    else if(bpp <= 16) {

        linesize = width * 2;

        bytespp = 2;

    } else if(bpp <= 24) {

        linesize = width * 3;

        bytespp = 3;

    } else {

        linesize = width * 4;

        bytespp = 4;

    }



    /* rows are DWORD right aligned*/

    if (does_round)

        *pitch = (linesize + 3) & -4;

    else

        *pitch = linesize;

    return bytespp;

}





int CGif89a::LWZReadByte (FILE *src, int flag, int input_code_size)

{

    int code, incode;

    register int i;

    static int fresh = FALSE;

    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 int table[2][(1 << MAX_LWZ_BITS)];

    static int stack[(1 << (MAX_LWZ_BITS)) * 2], *sp;



    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_size = 2 * clear_code;

        max_code = clear_code + 2;



        GetCode(src, 0, TRUE);



        fresh = TRUE;



        for (i = 0; i < clear_code; ++i) 

		{

            table[0][i] = 0;

            table[1][i] = i;

        }

        for (; i < (1 << MAX_LWZ_BITS); ++i)

            table[0][i] = table[1][0] = 0;



        sp = stack;



        return 0;

    } 

	else if (fresh) 

    {

        fresh = FALSE;

        do 

		{

            firstcode = oldcode = GetCode(src, code_size, FALSE);

        } while (firstcode == clear_code);

        return firstcode;

    }

    if (sp > stack)

        return *--sp;



    while ((code = GetCode(src, code_size, FALSE)) >= 0) 

	{

        if (code == clear_code) 

		{

            for (i = 0; i < clear_code; ++i) 

			{

                table[0][i] = 0;

                table[1][i] = i;

            }

            for (; i < (1 << MAX_LWZ_BITS); ++i)

                table[0][i] = table[1][i] = 0;

            code_size = set_code_size + 1;

            max_code_size = 2 * clear_code;

            max_code = clear_code + 2;

            sp = stack;

            firstcode = oldcode = GetCode(src, code_size, FALSE);

            return firstcode;

        } 

		else if (code == end_code) 

		{

            int count;

            unsigned char buf[260];



            if (ZeroDataBlock)

                return -2;



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



            if (count != 0) {

                /*

                 * fprintf (stderr,"missing EOD in data stream (common occurence)");

                 */

            }

            return -2;

        }

        incode = code;



        if (code >= max_code) 

		{

            *sp++ = firstcode;

            code = oldcode;

        }

        while (code >= clear_code) 

		{

            *sp++ = table[1][code];

            if (code == table[0][code])

                fprintf (stderr,"load_gif: circular table entry\n");

            code = table[0][code];

        }



        *sp++ = firstcode = table[1][code];



        if ((code = max_code) < (1 << MAX_LWZ_BITS)) 

		{

            table[0][code] = oldcode;

            table[1][code] = firstcode;

            ++max_code;

            if ((max_code >= max_code_size) && (max_code_size < (1 << MAX_LWZ_BITS))) 

           	{

                max_code_size *= 2;

                ++code_size;

            }

        }

        oldcode = incode;



        if (sp > stack)

            return *--sp;

    }

    return code;

}



int CGif89a::ReadImage (FILE* src, MYBITMAP* bmp, FRAME * f, int ignore)

{



    unsigned char c;

    int v;

    int xpos = 0, ypos = 0, pass = 0;



    /*initialize the compression routines*/

    if (!fread(&c, sizeof(char), 1, src)) 

	{

        fprintf (stderr,"load_gif: eof on image data\n");

        return -1;

    }

    if (LWZReadByte(src, TRUE, c) < 0) 

	{

        fprintf (stderr,"load_gif: error reading image\n");

        return -1;

    }

    /*if this is an "uninteresting picture" ignore it.*/

    if (ignore) 

	{

        while (LWZReadByte(src, FALSE, c) >= 0);

        return -0;

    }

    /*image = imagenewcmap(len, height, cmapsize);*/



    bmp->w = f->imageWidth;

    bmp->h = f->imageHeight;



    bmp->flags = MYBMP_FLOW_DOWN;



    if (f->ctrlExt.trsFlag) 

	{

        bmp->flags |= MYBMP_TRANSPARENT;

        bmp->transparent = f->ctrlExt.trsColorIndex;

    }

    bmp->frames = 1;

    bmp->depth = 8;

    bmpComputePitch (bmp->depth, bmp->w, &bmp->pitch, TRUE);

    bmp->bits = malloc (bmp->h * bmp->pitch);



    if(!bmp->bits)

        return -1;



    while ((v = LWZReadByte(src, FALSE, c)) >= 0) 

	{

#if 0

		int index = (ypos) * bmp->pitch + (xpos)*3;

		bmp->bits[index + 0 ] = ImageDesc->ColorMap[CM_RED][v]; 

		bmp->bits[index + 1 ] = ImageDesc->ColorMap[CM_GREEN][v];

		bmp->bits[index + 2 ] = ImageDesc->ColorMap[CM_BLUE][v];

#else		

    	 bmp->bits[ypos * bmp->pitch + xpos] = v;

#endif

        ++xpos;

        if (xpos == f->imageWidth) 

		{

            xpos = 0;

            if (f->interlaceFlag) 

			{

                switch (pass) 

				{

                case 0:

                case 1:

                    ypos += 8;

                    break;

                case 2:

                    ypos += 4;

                    break;

                case 3:

                    ypos += 2;

                    break;

                }



                if (ypos >= f->imageHeight) 

				{

                    ++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 >= f->imageHeight)

            break;

    }



fini:

    return 0;

}



BOOL CGif89a::getAllFrames(FILE* ifs)

{

	BYTE be;

	BOOL fileEnd = FALSE;

⌨️ 快捷键说明

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