📄 ximagif.cpp
字号:
} // 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(register 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 ((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) { 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++ = 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 ((ret = (short)out_line(iter, buf, linewidth)) < 0) { delete[] buf; return(ret); } bufptr = buf; bufcnt = linewidth; } } } } ret = 0; if (bufcnt != linewidth) 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; ) { if (fp->Read(&ch, sizeof(ch), 1) != 1) {break;} if (bPreviousWasNull || ch==0) { switch (ch)
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -