📄 gifcls.cpp
字号:
/*
** 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 + -