GIFDECOD.CPP
资源名称:Cimage.zip [点击查看]
上传用户:wep9318
上传日期:2007-01-07
资源大小:893k
文件大小:10k
源码类别:
图片显示
开发平台:
Visual C++
- /* 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.
- *
- */
- #include "stdafx.h"
- #include "gifdecod.h"
- #ifdef _DEBUG
- #define new DEBUG_NEW
- #undef THIS_FILE
- static char THIS_FILE[] = __FILE__;
- #endif
- static LONG code_mask[13]=
- {
- 0,
- 0x0001, 0x0003,
- 0x0007, 0x000F,
- 0x001F, 0x003F,
- 0x007F, 0x00FF,
- 0x01FF, 0x03FF,
- 0x07FF, 0x0FFF
- };
- /* This function initializes the decoder for reading a new image.
- */
- SHORT GIFDecoder::init_exp(SHORT size)
- {
- curr_size = size + 1;
- top_slot = 1 << curr_size;
- clear = 1 << size;
- ending = clear + 1;
- slot = newcodes = ending + 1;
- navail_bytes = nbits_left = 0;
- 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 GIFDecoder::get_next_code()
- {
- SHORT i, x;
- ULONG 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 = get_byte()) < 0)
- return(navail_bytes);
- else if (navail_bytes)
- {
- for (i = 0; i < navail_bytes; ++i)
- {
- if ((x = get_byte()) < 0)
- return(x);
- byte_buff[i] = x;
- }
- }
- }
- b1 = *pbytes++;
- nbits_left = 8;
- --navail_bytes;
- }
- 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 = get_byte()) < 0)
- return(navail_bytes);
- else if (navail_bytes)
- {
- for (i = 0; i < navail_bytes; ++i)
- {
- if ((x = get_byte()) < 0)
- return(x);
- byte_buff[i] = x;
- }
- }
- }
- b1 = *pbytes++;
- ret |= b1 << nbits_left;
- nbits_left += 8;
- --navail_bytes;
- }
- nbits_left -= curr_size;
- ret &= code_mask[curr_size];
- return((SHORT)(ret));
- }
- /* The reason we have these seperated like this instead of using
- * a structure like the original Wilhite code did, is because this
- * stuff generally produces significantly faster code when compiled...
- * This code is full of similar speedups... (For a good book on writing
- * C for speed or for space optomisation, see Efficient C by Tom Plum,
- * published by Plum-Hall Associates...)
- */
- LOCAL byte stack[MAX_CODES + 1]; /* Stack for storing pixels */
- LOCAL byte suffix[MAX_CODES + 1]; /* Suffix table */
- LOCAL USHORT prefix[MAX_CODES + 1]; /* Prefix linked list */
- /* 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)
- *
- */
- SHORT GIFDecoder::decoder(SHORT linewidth, INT& bad_code_count)
- {
- FAST byte *sp, *bufptr;
- byte *buf;
- FAST SHORT code, fc, oc, bufcnt;
- SHORT c, size, ret;
- /* Initialize for decoding a new image...
- */
- bad_code_count = 0;
- if ((size = get_byte()) < 0)
- return(size);
- if (size < 2 || 9 < size)
- return(BAD_CODE_SIZE);
- /* out_line = outline;*/
- init_exp(size);
- // printf("L %d %xn",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()) != 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 = size + 1;
- slot = newcodes;
- top_slot = 1 << curr_size;
- /* Continue reading codes until we get a non-clear code
- * (Another unlikely, but possible case...)
- */
- while ((c = get_next_code()) == 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++ = c;
- if (--bufcnt == 0)
- {
- if ((ret = out_line(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++ = 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++ = code;
- if (slot < top_slot)
- {
- suffix[slot] = fc = 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 = out_line(buf, linewidth)) < 0)
- {
- delete[] buf;
- return(ret);
- }
- bufptr = buf;
- bufcnt = linewidth;
- }
- }
- }
- }
- ret = 0;
- if (bufcnt != linewidth)
- ret = out_line(buf, (linewidth - bufcnt));
- delete[] buf;
- return(ret);
- }