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

📄 ximagif.cpp

📁 用Cximage 库显示各种格式图片小程序
💻 CPP
📖 第 1 页 / 共 4 页
字号:
		}
		return 0;
	} else {
		if (iter->ItOK()) {
			iter->SetRow(pixels, linelen);
			(void)iter->PrevRow();
			return 0;
		} else {
			//	 puts("chafeo");
			return -1;
		}
	}
}
////////////////////////////////////////////////////////////////////////////////
#if CXIMAGE_SUPPORT_ENCODE
////////////////////////////////////////////////////////////////////////////////
// SaveFile - writes GIF87a gif file
// Randy Spann 6/15/97
// R.Spann@ConnRiver.net
bool CxImageGIF::Encode(CxFile * fp)
{
	if (EncodeSafeCheck(fp)) return false;

	if(head.biBitCount > 8)	{
		//strcpy(info.szLastError,"GIF Images must be 8 bit or less");
		//return FALSE;
		return EncodeRGB(fp);
	}

	if ( GetNumFrames()>1 && ppFrames ) {
		return Encode(fp, ppFrames, GetNumFrames() );
	}

	EncodeHeader(fp);

	EncodeExtension(fp);

	EncodeComment(fp);

	EncodeBody(fp);

	fp->PutC(';'); // Write the GIF file terminator

	return true; // done!
}
////////////////////////////////////////////////////////////////////////////////
bool CxImageGIF::Encode(CxFile * fp, CxImage ** pImages, int pagecount, bool bLocalColorMap, bool bLocalDispMeth)
{
  cx_try {
	if (fp==NULL) cx_throw("invalid file pointer");
	if (pImages==NULL || pagecount<=0 || pImages[0]==NULL) cx_throw("multipage GIF, no images!");

	int i;
	for (i=0; i<pagecount; i++){
		if (pImages[i]==NULL)
			cx_throw("Bad image pointer");
		if (!(pImages[i]->IsValid()))
			cx_throw("Empty image");
		if (pImages[i]->GetNumColors()==0)
			cx_throw("CxImageGIF::Encode cannot create animated GIFs with a true color frame. Use DecreaseBpp before");
	}

	CxImageGIF ghost;

	//write the first image
	ghost.Ghost(pImages[0]);
	ghost.EncodeHeader(fp);

	if (m_loops!=1){
		ghost.SetLoops(max(0,m_loops-1));
		ghost.EncodeLoopExtension(fp);
	}

	if (bLocalDispMeth) {
		ghost.EncodeExtension(fp);
	} else {
		BYTE dm = ghost.GetDisposalMethod();
		ghost.SetDisposalMethod(GetDisposalMethod());
		ghost.EncodeExtension(fp);
		ghost.SetDisposalMethod(dm);
	}

	EncodeComment(fp);

	ghost.EncodeBody(fp);

	for (i=1; i<pagecount; i++){
		ghost.Ghost(pImages[i]);

		if (bLocalDispMeth) {
			ghost.EncodeExtension(fp);
		} else {
			BYTE dm = ghost.GetDisposalMethod();
			ghost.SetDisposalMethod(GetDisposalMethod());
			ghost.EncodeExtension(fp);
			ghost.SetDisposalMethod(dm);
		}

		ghost.EncodeBody(fp,bLocalColorMap);
	}

	fp->PutC(';'); // Write the GIF file terminator

  } cx_catch {
	  if (strcmp(message,"")) strncpy(info.szLastError,message,255);
	  return false;
  }
	return true;
}
////////////////////////////////////////////////////////////////////////////////
void CxImageGIF::EncodeHeader(CxFile *fp)
{
	fp->Write("GIF89a",1,6);	   //GIF Header

	Putword(head.biWidth,fp);			   //Logical screen descriptor
	Putword(head.biHeight,fp);

	BYTE Flags;
	if (head.biClrUsed==0){
		Flags=0x11;
	} else {
		Flags = 0x80;
		Flags |=(head.biBitCount - 1) << 5;
		Flags |=(head.biBitCount - 1);
	}

	fp->PutC(Flags); //GIF "packed fields"
	fp->PutC(0);	 //GIF "BackGround"
	fp->PutC(0);	 //GIF "pixel aspect ratio"

	if (head.biClrUsed!=0){
		RGBQUAD* pPal = GetPalette();
		for(DWORD i=0; i<head.biClrUsed; ++i) 
		{
			fp->PutC(pPal[i].rgbRed);
			fp->PutC(pPal[i].rgbGreen);
			fp->PutC(pPal[i].rgbBlue);
		}
	}
}
////////////////////////////////////////////////////////////////////////////////
void CxImageGIF::EncodeExtension(CxFile *fp)
{
	// TRK BEGIN : transparency
	fp->PutC('!');
	fp->PutC(TRANSPARENCY_CODE);

	gifgce.flags = 0;
	gifgce.flags |= ((info.nBkgndIndex != -1) ? 1 : 0);
	gifgce.flags |= ((GetDisposalMethod() & 0x7) << 2);
	gifgce.delaytime = (WORD)info.dwFrameDelay;
	gifgce.transpcolindex = (BYTE)info.nBkgndIndex;	   

	//Invert byte order in case we use a byte order arch, then set it back <AMSN>
	gifgce.delaytime = ntohs(gifgce.delaytime);
	fp->PutC(sizeof(gifgce));
	fp->Write(&gifgce, sizeof(gifgce), 1);
	gifgce.delaytime = ntohs(gifgce.delaytime);

	fp->PutC(0);
	// TRK END
}
////////////////////////////////////////////////////////////////////////////////
void CxImageGIF::EncodeLoopExtension(CxFile *fp)
{
	fp->PutC('!');		//byte  1  : 33 (hex 0x21) GIF Extension code
	fp->PutC(255);		//byte  2  : 255 (hex 0xFF) Application Extension Label
	fp->PutC(11);		//byte  3  : 11 (hex (0x0B) Length of Application Block (eleven bytes of data to follow)
	fp->Write("NETSCAPE2.0",11,1);
	fp->PutC(3);			//byte 15  : 3 (hex 0x03) Length of Data Sub-Block (three bytes of data to follow)
	fp->PutC(1);			//byte 16  : 1 (hex 0x01)
	Putword(m_loops,fp); //bytes 17 to 18 : 0 to 65535, an unsigned integer in lo-hi byte format. 
						//This indicate the number of iterations the loop should be executed.
	fp->PutC(0);			//bytes 19       : 0 (hex 0x00) a Data Sub-block Terminator. 
}
////////////////////////////////////////////////////////////////////////////////
void CxImageGIF::EncodeBody(CxFile *fp, bool bLocalColorMap)
{
	curx = 0;
	cury = head.biHeight - 1;	//because we read the image bottom to top
	CountDown = (long)head.biWidth * (long)head.biHeight;

	fp->PutC(',');

	Putword(info.xOffset,fp);
	Putword(info.yOffset,fp);
	Putword(head.biWidth,fp);
	Putword(head.biHeight,fp);

	BYTE Flags=0x00; //non-interlaced (0x40 = interlaced) (0x80 = LocalColorMap)
	if (bLocalColorMap)	{ Flags|=0x80; Flags|=head.biBitCount-1; }
	fp->PutC(Flags);

	if (bLocalColorMap){
		Flags|=0x87;
		RGBQUAD* pPal = GetPalette();
		for(DWORD i=0; i<head.biClrUsed; ++i) 
		{
			fp->PutC(pPal[i].rgbRed);
			fp->PutC(pPal[i].rgbGreen);
			fp->PutC(pPal[i].rgbBlue);
		}
	}

	int InitCodeSize = head.biBitCount <=1 ? 2 : head.biBitCount;
	 // Write out the initial code size
	fp->PutC((BYTE)InitCodeSize);

	 // Go and actually compress the data
	switch (GetCodecOption(CXIMAGE_FORMAT_GIF))
	{
	case 1:	//uncompressed
		compressNONE(InitCodeSize+1, fp);
		break;
	case 2: //RLE
		compressRLE(InitCodeSize+1, fp);
		break;
	default: //LZW
		compressLZW(InitCodeSize+1, fp);
	}

	 // Write out a Zero-length packet (to end the series)
	fp->PutC(0);
}
////////////////////////////////////////////////////////////////////////////////
void CxImageGIF::EncodeComment(CxFile *fp)
{
	unsigned long n = (unsigned long) strlen(m_comment);
	if (n>255) n=255;
	if (n) {
		fp->PutC('!');	//extension code:
		fp->PutC(254);	//comment extension
		fp->PutC((BYTE)n);	//size of comment
		fp->Write(m_comment,n,1);
		fp->PutC(0);	//block terminator
	}
}
////////////////////////////////////////////////////////////////////////////////
bool CxImageGIF::EncodeRGB(CxFile *fp)
{
	EncodeHeader(fp);

//	EncodeLoopExtension(fp);

	EncodeComment(fp);

	unsigned long w,h;
	w=h=0;
	const long cellw = 17;
	const long cellh = 15;
	CxImageGIF tmp;
	for (long y=0;y<head.biHeight;y+=cellh){
		for (long x=0;x<head.biWidth;x+=cellw){
			if ((head.biWidth -x)<cellw) w=head.biWidth -x; else w=cellw;
			if ((head.biHeight-y)<cellh) h=head.biHeight-y; else h=cellh;

			if (w!=tmp.GetWidth() || h!=tmp.GetHeight()) tmp.Create(w,h,8);

			if (IsTransparent()){
				tmp.SetTransIndex(0);
				tmp.SetPaletteColor(0,GetTransColor());
			}

			BYTE i;
			for (unsigned long j=0;j<h;j++){
				for (unsigned long k=0;k<w;k++){
					i=(BYTE)(1+k+cellw*j);
					tmp.SetPaletteColor(i,GetPixelColor(x+k,head.biHeight-y-h+j));
					tmp.SetPixelIndex(k,j,tmp.GetNearestIndex(tmp.GetPaletteColor(i)));
				}
			}

			tmp.SetOffset(x,y);
			tmp.EncodeExtension(fp);
			tmp.EncodeBody(fp,true);
		}
	}

	fp->PutC(';'); // Write the GIF file terminator

	return true; // done!
}
////////////////////////////////////////////////////////////////////////////////
#endif // CXIMAGE_SUPPORT_ENCODE
////////////////////////////////////////////////////////////////////////////////
// Return the next pixel from the image
// <DP> fix for 1 & 4 bpp images
int CxImageGIF::GifNextPixel( )
{
	if( CountDown == 0 ) return EOF;
	--CountDown;
	int r = GetPixelIndex(curx,cury);
	// Bump the current X position
	++curx;
	if( curx == head.biWidth ){
		curx = 0;
		cury--;	             //bottom to top
	}
	return r;
}
////////////////////////////////////////////////////////////////////////////////
void CxImageGIF::Putword(int w, CxFile *fp )
{
	fp->PutC((BYTE)(w & 0xff));
	fp->PutC((BYTE)((w >> 8) & 0xff));
}
////////////////////////////////////////////////////////////////////////////////
void CxImageGIF::compressNONE( int init_bits, CxFile* outfile)
{
	register long c;
	register long ent;

	// 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
	cur_accum = cur_bits = clear_flg = 0;
	maxcode = (short)MAXCODE(n_bits = g_init_bits);
	code_int maxmaxcode = (code_int)1 << MAXBITSCODES;

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

	a_count=0;
	ent = GifNextPixel( );

	output( (code_int)ClearCode );

	while ( ent != EOF ) {    
		c = GifNextPixel();

		output ( (code_int) ent );
		ent = c;
		if ( free_ent < maxmaxcode ) {  
			free_ent++;
		} else {
			free_ent=(short)(ClearCode+2);
			clear_flg=1;
			output((code_int)ClearCode);
		}
	}
	 // Put out the final code.
	output( (code_int) EOFCode );
}
////////////////////////////////////////////////////////////////////////////////

/***************************************************************************
 *
 *  GIFCOMPR.C       -     LZW GIF Image compression routines
 *
 ***************************************************************************/

void CxImageGIF::compressLZW( int init_bits, CxFile* outfile)
{
	register long fcode;
	register long c;
	register long ent;
	register long hshift;
	register long disp;
	register long i;

	// 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
	cur_accum = cur_bits = clear_flg = 0;
	maxcode = (short)MAXCODE(n_bits = g_init_bits);
	code_int maxmaxcode = (code_int)1 << MAXBITSCODES;

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

	a_count=0;
	ent = GifNextPixel( );

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

	while ( (c = GifNextPixel( )) != EOF ) {    

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

		if ( HashTabOf (i) == fcode ) {
			ent = CodeTabOf (i);
			continue;
		} else if ( (long)HashTabOf (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 ( HashTabOf (i) == fcode ) {	ent = CodeTabOf (i); continue; }
		if ( (long)HashTabOf (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_hash((long)HSIZE);

⌨️ 快捷键说明

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