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

📄 gifcls.cpp

📁 WIN32高级程序设计书附源码
💻 CPP
📖 第 1 页 / 共 2 页
字号:
/*
**  GIFCLS.CPP
**  GIF file reading class implementation.
**  This code creates reads a GIF file and creates a DIB.
**
**  This code originates from Martin Heller's "IMAGE3" program,
**  and is used by kind permission.  Martin, in turn, derived the
**  code from Microsoft's SHOWDIB sample application and the public
**  domain WINFRACT program.
**
**  Author:     C A Marriott
**  Created:    16-FEB-93
**
**  Revised:
**  18-FEB-93   Added code to handle interlaced GIF files.
**  20-FEB-93   Converted into a C++ class.
*/

#include <windows.h>                        // required for all Windows apps
#include <windowsx.h>                       // additional macros, etc

#include "gifcls.h"                         // GIFCLASS header

#include <stdio.h>                          // standard I/O library
#include <string.h>                         // string library

const WORD FILEBUFFER_SIZE = 20000;         // size of file buffer


//  GIF::GIF
//  Default constructor for the GIF class.

GIF::GIF()

{
    // Allocate a buffer for file input.

    cFileBuffer = (BYTE FAR *) GlobalAllocPtr( GMEM_MOVEABLE, FILEBUFFER_SIZE );
}


//  GIF::~GIF
//  Destructor for the GIF class.

GIF::~GIF()

{
    // Free the file buffer.

    GlobalFreePtr( cFileBuffer );
}


//  GIF::Read
//  Main entry point for GIF reader class.
//  This function reads a GIF file, creating a CF_DIB memory block
//  containing a DIB of that image.

HANDLE GIF::Read( LPSTR szFileName )

//  Input arguments:
//  szFileName          Full pathname of file to read.
//
//  Return value:
//  Handle to CF_DIB memory block if successful.
//  NULL if unsuccessful.

{
    int nNumColours;                        // number of colours in image
    BYTE buffer[16];                        // temporary input buffer
    WORD wWidth;                            // image width
    BOOL bFinished;                         // file completion flag
    HANDLE hDIB = NULL;                     // CF_DIB handle
    LPBITMAPINFOHEADER lpbi;                // bitmap header information
    RGBQUAD FAR *pRgb;                      // pointer to bitmap header info
	int status = 0;
    int nTmp;                               // temporary workspace
    int i, j, planes;
    DWORD dwBits;                           // size of bitmaps bits
    DWORD dwLen;                            // size of whole CF_DIB block
    OFSTRUCT of;                            // file information structure

    // Initialize the row count and pass number for line output.

    wRowCount = 0;
    nPassNumber = 0;

    wByteCount = 0;
    wByteIndex = 0;

    // Open the file.  If we fail to do so, exit with a failure code.

    hFile = OpenFile( szFileName, (LPOFSTRUCT)&of, OF_READ );
    if (hFile == -1) {
        return NULL;
    }

    // Read the "signature" from the start of the file.

    for (i=0; i<6; i++) {
        if ((nTmp = GetByte()) < 0) {
            CleanData();
            return NULL;
        }
        else
            buffer[i] = (BYTE) nTmp;
    }

    // If the signature is invalid, exit.

    if (strncmp( (char *) buffer, "GIF", 3) ||
		 buffer[3] < '0' || buffer[3] > '9' ||
		 buffer[4] < '0' || buffer[4] > '9' ||
		 buffer[5] < 'A' || buffer[5] > 'z') {
        CleanData();
        return NULL;
    }

    // Read the Logical Screen Descriptor.

    for (i=0; i<7; i++) {
        if ((nTmp = GetByte()) < 0) {
            CleanData();
            return NULL;
        }
        else
            buffer[i] = (BYTE) nTmp;
    }

    // Get the number of colour planes in the original image.

    planes = (buffer[4] & 0x7) + 1;

    // If there isn't a global colour table, exit.

    if ((buffer[4] & 0x80) == 0) {
        CleanData();
        return NULL;
    }

    // Get the size of the global colour table.

    nNumColours = 1 << planes;

    // Read the global colour table.

    for (i=0; i<nNumColours; i++) {

        // Each entry in the colour table consists of red, green, and
        // blue bytes.

        for (j=0; j<3; j++) {

            if ((nTmp = GetByte()) < 0) {
                CleanData();
                return NULL;
            }
            else
                buffer[j] = (BYTE) nTmp;

            // Store the colour in the global colour table.

            GCT[i][j] = buffer[j];
        }
    }

    // Now read the GIF data objects:

    bFinished = FALSE;

    while (bFinished==FALSE) {

        // Read the header.  This byte tells us what we have.

        switch (GetByte()) {

            // Trailer block - end of the dataset!

            case 0x3B:

                bFinished = TRUE;
                status = 0;
                break;

            // Extension block.

            case 0x21:

                // Read and ignore the extension ID.

                GetByte();

                // Read the data block length until we get a termination
                // block.

                while ((i=GetByte()) > 0) {

                    // Read and discard the data bytes in the block.

                    for (j=0; j<i; j++)
                        GetByte();
                }

                break;

            // Image block:

            case 0x2C:

                // Read the image header block.

                for (i=0; i<9; i++) {
                    if ((nTmp = GetByte()) < 0) {
                        status = -1;
                        break;
                    }
                    else
                        buffer[i] = (BYTE) nTmp;
                }

                // If the read failed, exit.

                if (status<0) {
                    bFinished = TRUE;
                    break;
				}

                // Get the image width and height, in pixels.

                wWidth = buffer[4] | buffer[5] << 8;
                wHeight = buffer[6] | buffer[7] << 8;

                // Set a flag indicating whether or not the image
                // is interlaced.

                bInterlaced = (buffer[8] & 0x40) ? TRUE : FALSE;

                // Create a DIB header describing the image:

                // Store the width and height of the image.

                xdots = wWidth;
                ydots = wHeight;
                colors = nNumColours;

                // If the image has more than 16 colours, create a
                // 256-colour DIB.

                if (colors>16) colors = 256;

                // If the image has between 3 and 16 colours, create a
                // 16-colour DIB.

                if (colors>2 && colors<16) colors = 16;

                // Set up default values for a 256-colour DIB.

                win_xdots = (xdots + 3) & 0xFFFC;
                win_ydots = ydots;
                pixelshift_per_byte = 0;
                pixels_per_byte = 1;
                pixels_per_bytem1 = 0;

                // Set up values for a 16-colour bitmap.

                if (colors == 16) {
                    win_xdots = (xdots + 7) & 0xFFF8;
                    pixelshift_per_byte = 1;
                    pixels_per_byte = 2;
                    pixels_per_bytem1 = 1;
                    win_andmask[0] = 0xF0;
                    win_notmask[0] = 0xF;
                    win_bitshift[0] = 4;
                    win_andmask[1] = 0xF;
                    win_notmask[1] = 0xF0;
                    win_bitshift[1] = 0;
                }

                // Set up values for a 2-colour bitmap.

                if (colors == 2) {
                    win_xdots = (xdots + 31) & 0xFFE0;
                    pixelshift_per_byte = 3;
                    pixels_per_byte = 8;
                    pixels_per_bytem1 = 7;
                    win_andmask[0] = 0x80;
                    win_notmask[0] = 0x7F;
                    win_bitshift[0] = 7;
                    for (i=1; i<8; i++) {
                        win_andmask[i] = win_andmask[i-1] >> 1;
                        win_notmask[i] = (win_notmask[i-1] >> 1) + 0x80;
                        win_bitshift[i] = win_bitshift[i-1] - 1;
					}
				}

                // Store the number of bytes per line of pixels.

                bytes_per_pixelline = win_xdots >> pixelshift_per_byte;

                // Allocate memory for a BITMAPINFO structure.

                hDIB = GlobalAlloc(GHND, (LONG) sizeof(BITMAPINFOHEADER) +
                                   colors * sizeof(RGBQUAD));

                if (hDIB==NULL)
                    return NULL;

                // Fill in the BITMAPINFOHEADER.

                lpbi = (LPBITMAPINFOHEADER) (VOID FAR *) GlobalLock(hDIB);
                lpbi->biSize = sizeof(BITMAPINFOHEADER);
                lpbi->biWidth = wWidth;
                lpbi->biHeight = wHeight;
                lpbi->biPlanes = 1;
                lpbi->biBitCount = 8/pixels_per_byte;
                lpbi->biCompression = BI_RGB;
                dwBits =
                         lpbi->biSizeImage = (DWORD) bytes_per_pixelline * win_ydots;
                lpbi->biXPelsPerMeter = 0;
                lpbi->biYPelsPerMeter = 0;
                lpbi->biClrUsed = colors;
                lpbi->biClrImportant = colors;

                win_bitmapsize = (((long) win_xdots * (long) win_ydots) >> pixelshift_per_byte) + 1;

                /* fill in intensities for all palette entry colors */

                pRgb = (RGBQUAD FAR *) ((LPSTR) lpbi + lpbi->biSize);
                for (i=0; i<colors; i++) {
                    pRgb[i].rgbRed = ((BYTE) GCT[i][0]);
                    pRgb[i].rgbGreen = ((BYTE) GCT[i][1]);
                    pRgb[i].rgbBlue = ((BYTE) GCT[i][2]);
				}

                // Find the size of the total CF_DIB memory block.

                dwLen = lpbi->biSize + (DWORD) colors * sizeof(RGBQUAD) + dwBits;

                // Increase the size of the memory block to make room for
                // the image bits.

                hDIB = GlobalReAlloc( hDIB, dwLen,
                                      GMEM_MOVEABLE | GMEM_ZEROINIT );
                if (!hDIB) {
                    bFinished = TRUE;
                    status = -1;
                    break;
                }

                // Get a pointer to the start of the block.

                pixels = (BYTE huge *) GlobalLock(hDIB);

                // Move the pointer to point to the start of the bit data.

                pixels += dwLen - dwBits;

                // Read the image bits.

                Decoder((short)wWidth);

                GlobalUnlock(hDIB);

                bFinished = TRUE;
                break;

            default:
                status = -1;
                bFinished = TRUE;
                break;
        }
    }

    CleanData();

    // Return the handle to the image.

    return hDIB;
}


//  GIF::GetByte
//  Retrieve the next byte from the input file.

int GIF::GetByte()

{
    // If we've exhausted the input buffer, read the next bufferload
    // from the input file.

    if(wByteCount==0) {
        wByteCount = _lread( hFile, cFileBuffer, FILEBUFFER_SIZE);
        wByteIndex = 0;
    }

    // If there are still bytes in the file, return the next byte.

    if (wByteCount) {
        --wByteCount;
        return (cFileBuffer[wByteIndex++]);
    }

    // Otherwise, return an "end of file" code.

	else
        return -1;
}

#ifdef THIS_DOESNT_DO_ANYTHING

//  This function is called by "StorePixelLine" but doesn't do anything!!!
//  Taking it out has absolutely no effect as far as I can see. - CAM

//  GIF::StorePixel
//  Store a pixel in the DIB.

void GIF::StorePixel( int x, int y, int color )

{
	long i;

	i = win_ydots - 1 - y;
	i = (i * win_xdots) + x;

	if (x >= 0 && x < xdots && y >= 0 && y < ydots) {
		if (pixelshift_per_byte == 0) {
			pixels[i] = color % colors;
			}
		else {
			unsigned int j;

            j = (unsigned int) (i & pixels_per_bytem1);
			i = i >> pixelshift_per_byte;
			pixels[i] = (pixels[i] & win_notmask[j]) +
                 (((BYTE) (color % colors)) << win_bitshift[j]);
        }
    }
}

#endif


//  GIF::StorePixelLine
//  Store a line of pixels in the DIB.

int GIF::StorePixelLine( int rownum, int leftpt, int rightpt, BYTE FAR *localvalues)

{
	int i, len;
	long startloc;

	len = rightpt - leftpt;
	if (rightpt >= xdots)
		len = xdots - 1 - leftpt;
	startloc = win_ydots - 1 - rownum;
	startloc = (startloc * win_xdots) + leftpt;

    if (rownum<0 || rownum>=ydots || leftpt<0) {
		return (0);
    }

	if (pixelshift_per_byte == 0) {
		_fmemcpy(pixels+startloc,localvalues,len);	//mh--for efficiency
    }
	else {
		unsigned int j;
		long k;

⌨️ 快捷键说明

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