📄 ximagif.cpp
字号:
free_ent=(short)(ClearCode+2);
clear_flg=1;
output((code_int)ClearCode);
}
}
// Put out the final code.
output( (code_int)ent );
output( (code_int) EOFCode );
}
////////////////////////////////////////////////////////////////////////////////
static const unsigned long code_mask[] = { 0x0000, 0x0001, 0x0003, 0x0007, 0x000F,
0x001F, 0x003F, 0x007F, 0x00FF,
0x01FF, 0x03FF, 0x07FF, 0x0FFF,
0x1FFF, 0x3FFF, 0x7FFF, 0xFFFF };
////////////////////////////////////////////////////////////////////////////////
void CxImageGIF::output( code_int code)
{
cur_accum &= code_mask[ 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 = (short)MAXCODE(n_bits = g_init_bits);
clear_flg = 0;
} else {
++n_bits;
if ( n_bits == MAXBITSCODES )
maxcode = (code_int)1 << MAXBITSCODES; /* should NEVER generate this code */
else
maxcode = (short)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();
g_outfile->Flush();
if(g_outfile->Error()) strcpy(info.szLastError,"Write Error in GIF file");
}
}
////////////////////////////////////////////////////////////////////////////////
void CxImageGIF::cl_hash(long hsize)
{
register long *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 CxImageGIF::char_out(int c)
{
accum[a_count++]=(char)c;
if (a_count >=254)
flush_char();
}
void CxImageGIF::flush_char()
{
if (a_count > 0) {
g_outfile->PutC((BYTE)a_count);
g_outfile->Write(accum,1,a_count);
a_count=0;
}
}
/*******************************************************************************
* GIF decoder
*******************************************************************************/
/* DECODE.C - An LZW decoder for GIF
* Copyright (C) 1987, by Steven A. Bennett
* Copyright (C) 1994, C++ version by Alejandro Aguilar Sierra
*
* Permission is given by the author to freely redistribute and include
* this code in any program as long as this credit is given where due.
*
* In accordance with the above, I want to credit Steve Wilhite who wrote
* the code which this is heavily inspired by...
*
* GIF and 'Graphics Interchange Format' are trademarks (tm) of
* Compuserve, Incorporated, an H&R Block Company.
*
* Release Notes: This file contains a decoder routine for GIF images
* which is similar, structurally, to the original routine by Steve Wilhite.
* It is, however, somewhat noticably faster in most cases.
*
*/
////////////////////////////////////////////////////////////////////////////////
short CxImageGIF::init_exp(short size)
{
curr_size = (short)(size + 1);
top_slot = (short)(1 << curr_size);
clear = (short)(1 << size);
ending = (short)(clear + 1);
slot = newcodes = (short)(ending + 1);
navail_bytes = nbits_left = 0;
memset(stack,0,MAX_CODES + 1);
memset(prefix,0,MAX_CODES + 1);
memset(suffix,0,MAX_CODES + 1);
return(0);
}
////////////////////////////////////////////////////////////////////////////////
/* get_next_code()
* - gets the next code from the GIF file. Returns the code, or else
* a negative number in case of file errors...
*/
short CxImageGIF::get_next_code(CxFile* file)
{
short i, x;
DWORD ret;
if (nbits_left == 0) {
if (navail_bytes <= 0) {
/* Out of bytes in current block, so read next block */
pbytes = byte_buff;
if ((navail_bytes = (short)get_byte(file)) < 0)
return(navail_bytes);
else if (navail_bytes) {
for (i = 0; i < navail_bytes; ++i) {
if ((x = (short)get_byte(file)) < 0) return(x);
byte_buff[i] = (BYTE)x;
}
}
}
b1 = *pbytes++;
nbits_left = 8;
--navail_bytes;
}
if (navail_bytes<0) return ending; // prevent deadlocks (thanks to Mike Melnikov)
ret = b1 >> (8 - nbits_left);
while (curr_size > nbits_left){
if (navail_bytes <= 0){
/* Out of bytes in current block, so read next block*/
pbytes = byte_buff;
if ((navail_bytes = (short)get_byte(file)) < 0)
return(navail_bytes);
else if (navail_bytes){
for (i = 0; i < navail_bytes; ++i){
if ((x = (short)get_byte(file)) < 0) return(x);
byte_buff[i] = (BYTE)x;
}
}
}
b1 = *pbytes++;
ret |= b1 << nbits_left;
nbits_left += 8;
--navail_bytes;
}
nbits_left = (short)(nbits_left-curr_size);
ret &= code_mask[curr_size];
return((short)(ret));
}
////////////////////////////////////////////////////////////////////////////////
/* short decoder(linewidth)
* short linewidth; * Pixels per line of image *
*
* - This function decodes an LZW image, according to the method used
* in the GIF spec. Every *linewidth* "characters" (ie. pixels) decoded
* will generate a call to out_line(), which is a user specific function
* to display a line of pixels. The function gets it's codes from
* get_next_code() which is responsible for reading blocks of data and
* seperating them into the proper size codes. Finally, get_byte() is
* the global routine to read the next BYTE from the GIF file.
*
* It is generally a good idea to have linewidth correspond to the actual
* width of a line (as specified in the Image header) to make your own
* code a bit simpler, but it isn't absolutely necessary.
*
* Returns: 0 if successful, else negative. (See ERRS.H)
*
*/
/* bad_code_count is incremented each time an out of range code is read.
* When this value is non-zero after a decode, your GIF file is probably
* corrupt in some way...
*/
short CxImageGIF::decoder(CxFile* file, CImageIterator* iter, short linewidth, int &bad_code_count)
{
register BYTE *sp, *bufptr;
BYTE *buf;
register short code, fc, oc, bufcnt;
short c, size, ret;
/* Initialize for decoding a new image... */
bad_code_count = 0;
if ((size = (short)get_byte(file)) < 0) return(size);
if (size < 2 || 9 < size) return(BAD_CODE_SIZE);
// out_line = outline;
init_exp(size);
//printf("L %d %x\n",linewidth,size);
/* Initialize in case they forgot to put in a clear code.
* (This shouldn't happen, but we'll try and decode it anyway...)
*/
oc = fc = 0;
/* Allocate space for the decode buffer */
if ((buf = new BYTE[linewidth + 1]) == NULL) return(OUT_OF_MEMORY);
/* Set up the stack pointer and decode buffer pointer */
sp = stack;
bufptr = buf;
bufcnt = linewidth;
/* This is the main loop. For each code we get we pass through the
* linked list of prefix codes, pushing the corresponding "character" for
* each code onto the stack. When the list reaches a single "character"
* we push that on the stack too, and then start unstacking each
* character for output in the correct order. Special handling is
* included for the clear code, and the whole thing ends when we get
* an ending code.
*/
while ((c = get_next_code(file)) != ending) {
/* If we had a file error, return without completing the decode*/
if (c < 0){
delete [] buf;
return(0);
}
/* If the code is a clear code, reinitialize all necessary items.*/
if (c == clear){
curr_size = (short)(size + 1);
slot = newcodes;
top_slot = (short)(1 << curr_size);
/* Continue reading codes until we get a non-clear code
* (Another unlikely, but possible case...)
*/
while ((c = get_next_code(file)) == clear);
/* If we get an ending code immediately after a clear code
* (Yet another unlikely case), then break out of the loop.
*/
if (c == ending) break;
/* Finally, if the code is beyond the range of already set codes,
* (This one had better NOT happen... I have no idea what will
* result from this, but I doubt it will look good...) then set it
* to color zero.
*/
if (c >= slot) c = 0;
oc = fc = c;
/* And let us not forget to put the char into the buffer... And
* if, on the off chance, we were exactly one pixel from the end
* of the line, we have to send the buffer to the out_line()
* routine...
*/
*bufptr++ = (BYTE)c;
if (--bufcnt == 0) {
if (iter) {
if ((ret = (short)out_line(iter, buf, linewidth)) < 0) {
delete [] buf;
return(ret);
}
}
bufptr = buf;
bufcnt = linewidth;
}
} else {
/* In this case, it's not a clear code or an ending code, so
* it must be a code code... So we can now decode the code into
* a stack of character codes. (Clear as mud, right?)
*/
code = c;
/* Here we go again with one of those off chances... If, on the
* off chance, the code we got is beyond the range of those already
* set up (Another thing which had better NOT happen...) we trick
* the decoder into thinking it actually got the last code read.
* (Hmmn... I'm not sure why this works... But it does...)
*/
if (code >= slot && sp<(stack+MAX_CODES-1)) {
if (code > slot)
++bad_code_count;
code = oc;
*sp++ = (BYTE)fc;
}
/* Here we scan back along the linked list of prefixes, pushing
* helpless characters (ie. suffixes) onto the stack as we do so.
*/
while (code >= newcodes && sp<(stack+MAX_CODES-1)) {
*sp++ = suffix[code];
code = prefix[code];
}
/* Push the last character on the stack, and set up the new
* prefix and suffix, and if the required slot number is greater
* than that allowed by the current bit size, increase the bit
* size. (NOTE - If we are all full, we *don't* save the new
* suffix and prefix... I'm not certain if this is correct...
* it might be more proper to overwrite the last code...
*/
*sp++ = (BYTE)code;
if (slot < top_slot){
suffix[slot] = (BYTE)(fc = (BYTE)code);
prefix[slot++] = oc;
oc = c;
}
if (slot >= top_slot){
if (curr_size < 12) {
top_slot <<= 1;
++curr_size;
}
}
/* Now that we've pushed the decoded string (in reverse order)
* onto the stack, lets pop it off and put it into our decode
* buffer... And when the decode buffer is full, write another
* line...
*/
while (sp > stack) {
*bufptr++ = *(--sp);
if (--bufcnt == 0) {
if (iter) {
if ((ret = (short)out_line(iter, buf, linewidth)) < 0) {
delete [] buf;
return(ret);
}
}
bufptr = buf;
bufcnt = linewidth;
}
}
}
}
ret = 0;
if (bufcnt != linewidth && iter)
ret = (short)out_line(iter, buf, (linewidth - bufcnt));
delete [] buf;
return(ret);
}
////////////////////////////////////////////////////////////////////////////////
int CxImageGIF::get_num_frames(CxFile *fp,struct_TabCol* TabColSrc,struct_dscgif* dscgif)
{
struct_image image;
long pos=fp->Tell();
int nframes=0;
struct_TabCol TempTabCol;
memcpy(&TempTabCol,TabColSrc,sizeof(struct_TabCol));
char ch;
bool bPreviousWasNull = true;
for (BOOL bContinue = TRUE; bContinue; )
{
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -