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

📄 gif.cpp

📁 <精通Visual C++图像处理编程>源码 对于图像处理很有帮助
💻 CPP
📖 第 1 页 / 共 2 页
字号:
					++code_size;
				}
			}

		oldcode=incode;

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


BOOL CGif::ReadImage(FILE *fd, BYTE  * bigMemBuf, int width, int height,
					 BYTE cmap[3][MAXCOLORMAPSIZE], int interlace)
{
	BYTE 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 :

	ASSERT(LZWReadByte(fd,FALSE,c)>=0);

	return TRUE;
}

                                                                         
////////////
//
//	GIF writing section
//
////////////

/*
 * Bump the 'curx' and 'cury' to point to the next pixel
 */
void CGif::BumpPixel()
{
    /*
     * Bump the current X position
     */
    ++curx;

    if( curx == Width ) {
        curx = 0;
		++cury;
    }
}

/*******************************************************************************
* Return the next pixel from the image
*******************************************************************************/

int CGif::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 CGif::WriteGIFFile(LPCTSTR lpstrFileName,
							BYTE* buf,
							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(lpstrFileName,"wb");
	if (fp==NULL) 
	{
		m_strGIFError="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<ColorMapSize; ++i) 
	{
		fputc(Red[i],fp);
		fputc(Green[i],fp);
		fputc(Blue[i],fp);
	}

	fputc(',',fp);

	Putword(LeftOfs,fp);
	Putword(TopOfs,fp);
	Putword(Width,fp);
	Putword(Height,fp);

	fputc(0x00,fp);

    /*
     * Write out the initial code size
     */
    fputc( InitCodeSize, fp );
    /*
     * Go and actually compress the data
     */

    compress(  InitCodeSize+1, fp);

    /*
     * Write out a Zero-length packet (to end the series)
     */
    fputc( 0, fp );

    /*
     * Write the GIF file terminator
     */
    fputc( ';', fp );

    /*
     * And close the file
     */
    fclose( fp );

	return TRUE;
}

/*******************************************************************************
 * Write out a word to the GIF file
*******************************************************************************/

void CGif::Putword(int w, FILE *fp )
{
    fputc( w & 0xff, fp );
    fputc( (w / 256) & 0xff, fp );
}


/***************************************************************************
 *
 *  GIF Image compression section
 *
 *  Lempel-Ziv compression based on 'compress'.  GIF modifications by
 *  David Rowley (mgardi@watdcsu.waterloo.edu)
 *
 ***************************************************************************/

void CGif::compress( int init_bits, FILE* outfile)
{
    register long fcode;
    register code_int i /* = 0 */;
    register int c;
    register code_int ent;
    register code_int disp;
    register int hshift;

    /*
     * Set up the globals:  g_init_bits - initial number of bits
     *                      g_outfile   - pointer to output file
     */
    g_init_bits = init_bits;
    g_outfile = outfile;

    /*
     * Set up the necessary values
     */
    clear_flg = 0;
    maxcode = MAXCODE(n_bits = g_init_bits);

    ClearCode = (1 << (init_bits - 1));
    EOFCode = ClearCode + 1;
    free_ent = ClearCode + 2;

    char_init();

    ent = GIFNextPixel( );

    hshift = 0;
    for ( fcode = (long) HSIZE;  fcode < 65536L; fcode *= 2L )
        ++hshift;
    hshift = 8 - hshift;                /* set hash code range bound */

    cl_hash( (count_int) HSIZE);            /* clear hash table */

    output( (code_int)ClearCode );

    while ( (c = GIFNextPixel( )) != EOF ) 
	{	/* } */

        fcode = (long) (((long) c << maxbits) + ent);
        i = (((code_int)c << hshift) ^ ent);    /* xor hashing */

        if ( htab[i] == fcode ) {
            ent = codetab[i];
            continue;
        } else if ( (long)htab[i] < 0 )      /* empty slot */
            goto nomatch;
        disp = HSIZE - i;           /* secondary hash (after G. Knott) */
        if ( i == 0 )
            disp = 1;
probe:
        if ( (i -= disp) < 0 )
            i += HSIZE;

        if ( htab[i] == fcode ) {
            ent = codetab[i];
            continue;
        }
        if ( (long)htab[i] > 0 )
            goto probe;
nomatch:
        output ( (code_int) ent );
        ent = c;
        if ( free_ent < maxmaxcode ) 
		{	/* } */
            codetab[i] = free_ent++; /* code -> hashtable */
            htab[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.
 */

void CGif::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 CGif::cl_block()
{
	cl_hash((count_int)HSIZE);
	free_ent=ClearCode+2;
	clear_flg=1;

	output((code_int)ClearCode);
}

void CGif::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
*******************************************************************************/

void CGif::char_init()
{
	a_count=0;
}

void CGif::char_out(int c)
{
	accum[a_count++]=c;
	if (a_count >=254)
		flush_char();
}

void CGif::flush_char()
{
	if (a_count > 0) 
	{
		fputc(a_count,g_outfile);
		fwrite(accum,1,a_count,g_outfile);
		a_count=0;
	}
}

//
// copies BYTE buffer into DWORD-aligned BYTE buffer
// return addr of new buffer
//
BYTE* CGif::MakeDwordAlign(BYTE *dataBuf, UINT widthPix, UINT height, UINT *uiOutWidthBytes)		// bytes!!!
{
	////////////////////////////////////////////////////////////
	// what's going on here? this certainly means trouble 
	if (dataBuf==NULL)
		return NULL;

	////////////////////////////////////////////////////////////
	// how big is the smallest DWORD-aligned buffer that we can use?
	UINT uiWidthBytes;
	uiWidthBytes = WIDTHBYTES(widthPix * 24);

	DWORD dwNewsize=(DWORD)((DWORD)uiWidthBytes * 
							(DWORD)height);
	BYTE *pNew;

	////////////////////////////////////////////////////////////
	// alloc and open our new buffer
	pNew=(BYTE *)new BYTE[dwNewsize];
	if (pNew==NULL) 
	{
		return NULL;
	}
	
	////////////////////////////////////////////////////////////
	// copy row-by-row
	UINT uiInWidthBytes = widthPix * 3;
	UINT uiCount;
	for (uiCount=0;uiCount < height;uiCount++) 
	{
		BYTE * bpInAdd;
		BYTE * bpOutAdd;
		ULONG lInOff;
		ULONG lOutOff;

		lInOff=uiInWidthBytes * uiCount;
		lOutOff=uiWidthBytes * uiCount;

		bpInAdd= dataBuf + lInOff;
		bpOutAdd= pNew + lOutOff;

		memcpy(bpOutAdd,bpInAdd,uiInWidthBytes);
	}

	*uiOutWidthBytes=uiWidthBytes;
	return pNew;
}

//
//	vertically flip a buffer 
//	note, this operates on a buffer of widthBytes bytes, not pixels!!!
//
BOOL CGif::VertFlipBuf(BYTE  * inbuf, UINT widthBytes, UINT height)
{   
	BYTE  *tb1;
	BYTE  *tb2;

	if (inbuf==NULL)
		return FALSE;

	UINT bufsize;

	bufsize=widthBytes;

	tb1= (BYTE *)new BYTE[bufsize];
	if (tb1==NULL) {
		return FALSE;
	}

	tb2= (BYTE *)new BYTE [bufsize];
	if (tb1==NULL) 
	{
		return FALSE;
	}
	
	UINT row_cnt;     
	ULONG off1=0;
	ULONG off2=0;

	for (row_cnt=0;row_cnt<(height+1)/2;row_cnt++) 
	{
		off1=row_cnt*bufsize;
		off2=((height-1)-row_cnt)*bufsize;   
		
		memcpy(tb1,inbuf+off1,bufsize);
		memcpy(tb2,inbuf+off2,bufsize);	
		memcpy(inbuf+off1,tb2,bufsize);
		memcpy(inbuf+off2,tb1,bufsize);
	}	

	delete [] tb1;
	delete [] tb2;

	return TRUE;
}        


//
//	swap Rs and Bs
//
//	Note! this does its stuff on buffers with a whole number of pixels
//	per data row!!
//
BOOL CGif::BGRFromRGB(BYTE *buf, UINT widthPix, UINT height)
{
	if (buf==NULL)
		return FALSE;

	UINT col, row;
	for (row=0;row<height;row++) 
	{
		for (col=0;col<widthPix;col++) 
		{
			LPBYTE pRed, pGrn, pBlu;
			pRed = buf + row * widthPix * 3 + col * 3;
			pGrn = buf + row * widthPix * 3 + col * 3 + 1;
			pBlu = buf + row * widthPix * 3 + col * 3 + 2;

			// swap red and blue
			BYTE tmp;
			tmp = *pRed;
			*pRed = *pBlu;
			*pBlu = tmp;
		}
	}
	return TRUE;
}

BYTE* CGif::ClearDwordAlign(BYTE *inBuf, UINT widthPix, UINT height, UINT nBpp)
{
	if (inBuf==NULL)
		return FALSE;


	BYTE *tmp;
	tmp=(BYTE *)new BYTE[height * widthPix * nBpp/8];
	if (tmp==NULL)
		return NULL;

	UINT row;

	for (row=0;row<height;row++) 
	{
		memcpy((tmp+row * widthPix * nBpp/8), 
				(inBuf + row * WIDTHBYTES(widthPix * nBpp)), 
				widthPix * nBpp/8);
	}

	return tmp;
}

⌨️ 快捷键说明

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