📄 gif.cpp
字号:
++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 + -