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

📄 gifcls.cpp

📁 WIN32高级程序设计书附源码
💻 CPP
📖 第 1 页 / 共 2 页
字号:
		for (i = 0;  i <= len;  i++) {
			k = startloc + i;
            j = (unsigned int) (k & pixels_per_bytem1);
			k = k >> pixelshift_per_byte;
			pixels[k] = (pixels[k] & win_notmask[j]) +
                 (((BYTE) (localvalues[i] % colors)) << win_bitshift[j]);
        }
    }

//    StorePixel(leftpt, rownum, localvalues[0]);
	return (1);
}


//  GIF::OutputLine
//  Output a line of pixels.
//  This is where the code to handle interlaced images has been added - CAM

int GIF::OutputLine( BYTE FAR *localvalues, int nNumberOfDots )

{
    int nResult;                            // result code

    // Output the line of pixels.

    nResult =  StorePixelLine( wRowCount, 0, nNumberOfDots, localvalues);

    // If the image is non-interlaced, simply increment the row number.

    if (!bInterlaced)
        wRowCount++;

    else {

        // If the image is interlaced, the row number is changed according
        // to the interlacing pass we're currently on.

        switch (nPassNumber) {

            // On the first pass, output every 8th row, starting at row 0.

            case 0:

                wRowCount += 8;

                // If we've gone beyond the end of the image, we're now on
                // the second pass:

                if (wRowCount>=wHeight) {
                    nPassNumber = 1;
                    wRowCount = 4;
                }
                break;

            // On the second pass, output every 8th row, starting at row 4.

            case 1:

                wRowCount += 8;

                // If we've gone beyond the end of the image, we're now on
                // the 3rd pass:

                if (wRowCount>=wHeight) {
                    nPassNumber = 2;
                    wRowCount = 2;
                }
                break;

            // On the third pass, output every 4th row, starting at row 2.

            case 2:

                wRowCount += 4;

                // If we've gone beyond the end of the image, we're now on
                // the 4th pass:

                if (wRowCount>=wHeight) {
                    nPassNumber = 3;
                    wRowCount = 1;
                }
                break;

            // On the 4th pass, output every 2nd row starting at row 1.

            case 3:

                wRowCount += 2;
                break;
        }
    }

    return nResult;
}


//  GIF::CleanData
//  Clean up in preparation for a "graceful" exit after an error.

void GIF::CleanData()

{
    // Close the file.

    _lclose(hFile);
    hFile=NULL;
}


/* DECODE.C - An LZW decoder for GIF
 * Copyright (C) 1987, by Steven A. Bennett
 *
 * 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.
 *
 == This routine was modified for use in FRACTINT in two ways.
 ==
 == 1) The original #includes were folded into the routine strictly to hold
 ==    down the number of files we were dealing with.
 ==
 == 2) The 'stack', 'suffix', 'prefix', and 'buf' arrays were changed from
 ==    static and 'malloc()'ed to external only so that the assembler
 ==    program could use the same array space for several independent
 ==    chunks of code.	Also, 'stack' was renamed to 'dstack' for TASM
 ==    compatibility.
 ==
 == 3) The 'out_line()' external function has been changed to reference
 ==    '*outln()' for flexibility (in particular, 3D transformations)
 ==
 == 4) A call to 'keypressed()' has been added after the 'outln()' calls
 ==    to check for the presenc of a key-press as a bail-out signal
 ==
 == (Bert Tyler and Timothy Wegner)
 */

/* Various error codes used by decoder
 * and my own routines...   It's okay
 * for you to define whatever you want,
 * as long as it's negative...  It will be
 * returned intact up the various subroutine
 * levels...
 */
#define OUT_OF_MEMORY -10
#define BAD_CODE_SIZE -20
#define READ_ERROR -1
#define WRITE_ERROR -2
#define OPEN_ERROR -3
#define CREATE_ERROR -4


const LONG code_mask[13] = {
     0,
     0x0001, 0x0003,
     0x0007, 0x000F,
     0x001F, 0x003F,
     0x007F, 0x00FF,
     0x01FF, 0x03FF,
     0x07FF, 0x0FFF
};


//  GIF::InitializeDecoder
//  Initialize the LZW decoder.

void GIF::InitializeDecoder( short size )

//  Input arguments:
//  size                Initial code size, in bits.

{
	curr_size = size + 1;
	top_slot = 1 << curr_size;
	clear = 1 << size;
	ending = clear + 1;
	slot = newcodes = ending + 1;
	navail_bytes = nbits_left = 0;
}


//  GIF::GetNextCode
//  Retrieve the next code from the file.  Return the code,
//  or else a negative number in the case of a file error.

short GIF::GetNextCode()

{
	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 = GetByte()) < 0)
				return (navail_bytes);
			else if (navail_bytes) {
				for (i = 0;  i < navail_bytes;  ++i) {
                    if ((x = GetByte()) < 0)
						return (x);
                    byte_buff[i] =(BYTE)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 = GetByte()) < 0)
				return (navail_bytes);
			else if (navail_bytes) {
				for (i = 0;  i < navail_bytes;  ++i) {
                    if ((x = GetByte()) < 0)
						return (x);
                    byte_buff[i] =(BYTE)x;
					}
				}
			}
		b1 = *pbytes++;
		ret |= b1 << nbits_left;
		nbits_left += 8;
		--navail_bytes;
		}
	nbits_left -= curr_size;
	ret &= code_mask[curr_size];
	return ((short) (ret));
}


/* - 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 its codes from
 * get_next_code() which is responsible for reading blocks of data and
 * seperating them into the proper size codes.  Finally, GetByte() 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)
 *
 */

//  I've changed this function so that all the memory used (which was
//  previously global) is now allocated and freed locally.
//  Windows applications have local heap space restrictions!!!!
//  - CAM

short GIF::Decoder( short linewidth )

{
    BYTE FAR *sp;                           // stack pointer
    BYTE FAR *bufptr;                       // pointer to decoder buffer
    BYTE FAR *buf;                          // pointer to decoder buffer
    BYTE FAR *dstack;                       // decoder stack
    BYTE FAR *suffix;                       // suffix array
    BYTE FAR *decoderline;                  // decoded pixels array
    WORD FAR *prefix;                       // prefix array
    int nBufferLength;                      // length of output buffer
    short code, fc, oc, bufcnt;
	short c, size, ret;
	short xskip, yskip;
    const int MAX_CODES = 4095;             // size of LZW code table

    navail_bytes = 0;         /* # bytes left in block */
    nbits_left = 0;       /* # bits left in current byte */
    bad_code_count = 0;

    skipxdots = 0;
    skipydots = 0;

    // Initialize for decoding a new image.

    // Read the initial code size from the data stream.

    if ((size = GetByte()) < 0)
        return (size);

    if (size<2 || size>9)
        return (BAD_CODE_SIZE);

    InitializeDecoder( size );
	xskip = yskip = 0;

    // Allocate buffers.

    decoderline = (BYTE FAR *) GlobalAllocPtr( GMEM_MOVEABLE|GMEM_ZEROINIT,
                                               2049 );
    dstack = (BYTE FAR *) GlobalAllocPtr( GMEM_MOVEABLE|GMEM_ZEROINIT,
                                               MAX_CODES+1 );
    suffix = (BYTE FAR *) GlobalAllocPtr( GMEM_MOVEABLE|GMEM_ZEROINIT,
                                               MAX_CODES+1 );
    prefix = (WORD FAR *) GlobalAllocPtr( GMEM_MOVEABLE|GMEM_ZEROINIT,
                                               (MAX_CODES+1)*sizeof(WORD) );

   /* 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;

    // Set up the initial pointers.

	buf = decoderline;
	sp = dstack;
	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=GetNextCode()) != ending) {

      /* If we had a file error, return without completing the decode
       */
		if (c < 0)
			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 = GetNextCode()) == 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... */
            *sp++ = (BYTE)c;       /* let the common code outside the if else stuff it */
			}
        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) {
				fc = code;
                suffix[slot] = (BYTE)fc;
				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 > dstack) {
			--sp;
			if (--xskip < 0) {
				xskip = skipxdots;
				*bufptr++ = *sp;
				}
			if (--bufcnt == 0)	/* finished an input row? */
				{
                if (--yskip < 0) {
                    nBufferLength = (int) (bufptr - buf);
                    if ((ret = OutputLine(buf, nBufferLength)) < 0)
						return (ret);
					yskip = skipydots;
					}
				bufptr = buf;
				bufcnt = linewidth;
				xskip = 0;
				}
			}
		}
   /* PB note that if last line is incomplete, we're not going to try
      to emit it;  original code did, but did so via out_line and therefore
      couldn't have worked well in all cases... */

    // Free the allocated memory.

    GlobalFreePtr( decoderline );
    GlobalFreePtr( dstack );
    GlobalFreePtr( suffix );
    GlobalFreePtr( prefix );

	return (0);
}

⌨️ 快捷键说明

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