755 lines
23 KiB
C
755 lines
23 KiB
C
/*++
|
||
|
||
Copyright (c) 1990-1992 Microsoft Corporation
|
||
|
||
|
||
Module Name:
|
||
|
||
htuigif.c
|
||
|
||
|
||
Abstract:
|
||
|
||
This module contains GIF file decompression to generate a memory DIB type
|
||
bitmap for the GIF
|
||
|
||
Author:
|
||
|
||
21-Apr-1992 Tue 11:38:11 created -by- Daniel Chou (danielc)
|
||
|
||
|
||
[Environment:]
|
||
|
||
GDI Device Driver - Halftone.
|
||
|
||
|
||
[Notes:]
|
||
|
||
|
||
Revision History:
|
||
|
||
|
||
--*/
|
||
|
||
|
||
|
||
#include <stddef.h>
|
||
#include <windows.h>
|
||
|
||
#include <stdlib.h>
|
||
#include <string.h>
|
||
|
||
#include <ht.h>
|
||
|
||
#include "htuidlg.h"
|
||
#include "htuimain.h"
|
||
#include "htuigif.h"
|
||
|
||
extern HMODULE hHTUIModule;
|
||
|
||
|
||
//
|
||
// Following structures and #defines are only used in this C file
|
||
//
|
||
|
||
|
||
#pragma pack(1)
|
||
typedef struct _GIFRGB { /* gifrgb */
|
||
BYTE Red;
|
||
BYTE Green;
|
||
BYTE Blue;
|
||
} GIFRGB, FAR *PGIFRGB;
|
||
#pragma pack()
|
||
|
||
typedef struct _GIFMAP {
|
||
SHORT CurX;
|
||
SHORT CurY;
|
||
SHORT Width;
|
||
SHORT Height;
|
||
} GIFMAP;
|
||
|
||
#pragma pack(1)
|
||
typedef struct _GIFHEADER {
|
||
BYTE Signature[3]; /* This is the 'GIF' signature */
|
||
BYTE Version[3]; /* version number such as '89a' */
|
||
WORD Width; /* Width of the picture in pels */
|
||
WORD Height; /* Height of the picture in pels */
|
||
BYTE Flags; /* GIFH_xxxx flags */
|
||
BYTE BColorIndex; /* background color index */
|
||
BYTE AspectRatio; /* w/h ratio = (x + 15) / 64 */
|
||
} GIFHEADER, *PGIFHEADER;
|
||
#pragma pack()
|
||
|
||
#define GIFH_GLOBAL_COLOR_TABLE 0x80
|
||
#define GIFH_PRIMARY_COLOR_BITS 0xe0
|
||
#define GIFH_SORTED_COLORS 0x08
|
||
#define GIFH_SIZE_COLOR_TABLE 0x07
|
||
|
||
#define GIFMAP_INTERLACE 0x40
|
||
|
||
typedef struct _GIF2DIBINFO {
|
||
LPSHORT pLineIncVec;
|
||
LPBYTE pDIBLine1;
|
||
LPBYTE pDIBCurLine;
|
||
LPBYTE pDIBNow;
|
||
LPBYTE pGIFBuf;
|
||
DWORD SizeGIFBuf;
|
||
GIFMAP Map;
|
||
WORD cx;
|
||
WORD cy;
|
||
WORD cxBytes;
|
||
WORD LinesDone;
|
||
WORD RemainXPels;
|
||
WORD PelMask;
|
||
} GIF2DIBINFO, *PGIF2DIBINFO;
|
||
|
||
|
||
typedef VOID (*PFNOUTPUTPELS)(PGIF2DIBINFO pGIF2DIBInfo, UINT TotalPels);
|
||
|
||
#define SET_NEXT_DIB_PBUF \
|
||
{ \
|
||
SHORT LineInc; \
|
||
\
|
||
GIF2DIBInfo.pDIBCurLine -= \
|
||
(LONG)(LineInc = *(GIF2DIBInfo.pLineIncVec)) * \
|
||
(LONG)GIF2DIBInfo.cxBytes; \
|
||
\
|
||
if ((GIF2DIBInfo.Map.CurY += LineInc) >= GIF2DIBInfo.Map.Height) { \
|
||
\
|
||
GIF2DIBInfo.pLineIncVec++; \
|
||
\
|
||
if (*(GIF2DIBInfo.pLineIncVec) >= 0) { \
|
||
\
|
||
GIF2DIBInfo.Map.CurY = *(GIF2DIBInfo.pLineIncVec++); \
|
||
GIF2DIBInfo.pDIBCurLine = GIF2DIBInfo.pDIBLine1 - \
|
||
((LONG)GIF2DIBInfo.Map.CurX * \
|
||
(LONG)GIF2DIBInfo.Map.CurY); \
|
||
} \
|
||
} \
|
||
\
|
||
++GIF2DIBInfo.LinesDone; \
|
||
\
|
||
GIF2DIBInfo.pDIBNow = GIF2DIBInfo.pDIBCurLine; \
|
||
GIF2DIBInfo.RemainXPels = GIF2DIBInfo.cx; \
|
||
GIF2DIBInfo.PelMask = 0; \
|
||
} \
|
||
|
||
|
||
|
||
//////////////////////////////////////////////////////////////////////////////
|
||
// //
|
||
// LZW DeCompression //
|
||
// //
|
||
//////////////////////////////////////////////////////////////////////////////
|
||
|
||
|
||
#define MAXBITS 12
|
||
#define SIZE_GIF_BUF (60 * 1024)
|
||
#define SIZE_LZW_LASTCHAR (1 << MAXBITS)
|
||
#define SIZE_LZW_RASTERBLOCK 256
|
||
#define SIZE_LZW_PREFIX ((1 << MAXBITS) * 2)
|
||
#define SIZE_LZW_BUFS (SIZE_LZW_LASTCHAR + SIZE_LZW_RASTERBLOCK + \
|
||
SIZE_LZW_PREFIX)
|
||
|
||
typedef struct _LZWINFO {
|
||
LPBYTE pLastChar;
|
||
LPBYTE pRasterBlock;
|
||
LPSHORT pPrefix;
|
||
SHORT EODCode;
|
||
SHORT CSMask;
|
||
SHORT CodeSize;
|
||
SHORT BitsLeft;
|
||
DWORD CodeBuf;
|
||
SHORT GetCodeRet;
|
||
BYTE RBIndex;
|
||
BYTE RBLen;
|
||
} LZWINFO;
|
||
|
||
|
||
|
||
#define GET_GIF_CODE \
|
||
{ \
|
||
BOOL EODCodeBreak = FALSE; \
|
||
\
|
||
while (LZWInfo.BitsLeft < LZWInfo.CodeSize) { \
|
||
\
|
||
if (LZWInfo.RBIndex >= LZWInfo.RBLen) { \
|
||
\
|
||
if ((!ReadFile(hFile, &LZWInfo.RBLen, 1, &cbRead, NULL)) || \
|
||
(cbRead != 1) || \
|
||
(LZWInfo.RBLen < 1) || \
|
||
(!ReadFile(hFile, LZWInfo.pRasterBlock, LZWInfo.RBLen, \
|
||
&cbRead, NULL)) || \
|
||
(cbRead != (DWORD)LZWInfo.RBLen)) { \
|
||
\
|
||
EODCodeBreak = TRUE; \
|
||
break; \
|
||
} \
|
||
\
|
||
LZWInfo.RBIndex = 0; \
|
||
} \
|
||
\
|
||
LZWInfo.CodeBuf |= (DWORD)*(LZWInfo.pRasterBlock + \
|
||
LZWInfo.RBIndex++) << LZWInfo.BitsLeft; \
|
||
LZWInfo.BitsLeft += 8; \
|
||
} \
|
||
\
|
||
if (EODCodeBreak) { \
|
||
\
|
||
LZWInfo.GetCodeRet = LZWInfo.EODCode; \
|
||
\
|
||
} else { \
|
||
\
|
||
LZWInfo.GetCodeRet = (SHORT)(LZWInfo.CodeBuf & \
|
||
(DWORD)LZWInfo.CSMask); \
|
||
LZWInfo.CodeBuf >>= LZWInfo.CodeSize; \
|
||
LZWInfo.BitsLeft -= LZWInfo.CodeSize; \
|
||
} \
|
||
} \
|
||
|
||
|
||
BOOL
|
||
DeCompressGIFFileToDIB(
|
||
HANDLE hFile,
|
||
PGIF2DIBINFO pGIF2DIBInfo,
|
||
LPBYTE pLZWBuf,
|
||
PFNOUTPUTPELS pfnOutputPels,
|
||
WORD BitCount
|
||
)
|
||
{
|
||
LPBYTE pGIFBufBeg;
|
||
LPBYTE pGIFBufEnd;
|
||
LPBYTE pOutBufTail;
|
||
LPBYTE pOutBufHead;
|
||
LZWINFO LZWInfo;
|
||
UINT SizeGIFBuf;
|
||
DWORD cbRead;
|
||
WORD BytesMove;
|
||
SHORT FinalChar;
|
||
SHORT OldCode;
|
||
SHORT CurCode;
|
||
SHORT InitialCodeSize;
|
||
SHORT ClearCode;
|
||
SHORT MaxCode;
|
||
SHORT MaxCol;
|
||
SHORT NextCode;
|
||
BYTE bCh;
|
||
|
||
|
||
//
|
||
// First initialize all the local buffer
|
||
//
|
||
|
||
LZWInfo.pLastChar = pLZWBuf;
|
||
LZWInfo.pRasterBlock = pLZWBuf + SIZE_LZW_LASTCHAR;
|
||
LZWInfo.pPrefix = (LPSHORT)(LZWInfo.pRasterBlock +
|
||
SIZE_LZW_RASTERBLOCK);
|
||
LZWInfo.BitsLeft = 0;
|
||
LZWInfo.CodeBuf = 0;
|
||
LZWInfo.GetCodeRet = 0;
|
||
LZWInfo.RBIndex =
|
||
LZWInfo.RBLen = 0;
|
||
*(LZWInfo.pLastChar) = (BYTE)0;
|
||
*(LZWInfo.pPrefix) =
|
||
FinalChar =
|
||
OldCode = 0;
|
||
|
||
if ((!ReadFile(hFile, &bCh, 1, &cbRead, NULL)) ||
|
||
(cbRead != 1)) {
|
||
|
||
return(FALSE);
|
||
}
|
||
|
||
pGIFBufBeg = pGIF2DIBInfo->pGIFBuf;
|
||
SizeGIFBuf = (UINT)pGIF2DIBInfo->SizeGIFBuf;
|
||
pGIFBufEnd = pGIFBufBeg + SizeGIFBuf;
|
||
|
||
InitialCodeSize = (SHORT)bCh;
|
||
LZWInfo.CodeSize = ++InitialCodeSize;
|
||
|
||
if (LZWInfo.CodeSize < 3 || LZWInfo.CodeSize > 9) {
|
||
|
||
return(FALSE);
|
||
}
|
||
|
||
MaxCol = (SHORT)((1 << BitCount) - 1);
|
||
ClearCode = (SHORT)(1 << (LZWInfo.CodeSize - 1));
|
||
LZWInfo.EODCode = (SHORT)(ClearCode + 1);
|
||
NextCode = (SHORT)(ClearCode + 2);
|
||
MaxCode = (SHORT)(ClearCode << 1);
|
||
LZWInfo.CSMask = (SHORT)(MaxCode - 1);
|
||
pOutBufHead = pGIFBufBeg;
|
||
|
||
|
||
while (TRUE) {
|
||
|
||
//
|
||
// GET_GIF_CODE will reeurn from this function if _ReadFile() failed,
|
||
// otherwise it set the curretn read code into LZWInfo.GetCodeRet
|
||
//
|
||
|
||
GET_GIF_CODE;
|
||
|
||
if (LZWInfo.GetCodeRet == LZWInfo.EODCode) {
|
||
|
||
break; // Done
|
||
}
|
||
|
||
//
|
||
// Write out the color data if the buffer is full
|
||
//
|
||
|
||
if (pOutBufHead >= pGIFBufEnd) {
|
||
|
||
pfnOutputPels(pGIF2DIBInfo, (UINT)SizeGIFBuf);
|
||
pOutBufHead = pGIFBufBeg;
|
||
}
|
||
|
||
if (LZWInfo.GetCodeRet == ClearCode) {
|
||
|
||
LZWInfo.CodeSize = InitialCodeSize;
|
||
NextCode = (SHORT)(ClearCode + (SHORT)2);
|
||
MaxCode = (SHORT)(1 << LZWInfo.CodeSize);
|
||
LZWInfo.CSMask = (SHORT)(MaxCode - 1);
|
||
|
||
do {
|
||
|
||
GET_GIF_CODE;
|
||
|
||
} while (LZWInfo.GetCodeRet == ClearCode);
|
||
|
||
|
||
if (LZWInfo.GetCodeRet == LZWInfo.EODCode) {
|
||
|
||
break;
|
||
|
||
} else if (LZWInfo.GetCodeRet >= NextCode) {
|
||
|
||
LZWInfo.GetCodeRet = 0;
|
||
}
|
||
|
||
*pOutBufHead++ = (BYTE)(OldCode = FinalChar = LZWInfo.GetCodeRet);
|
||
|
||
} else {
|
||
|
||
CurCode = LZWInfo.GetCodeRet;
|
||
|
||
//
|
||
// At here, we guranteed that at least one byte in the buffer
|
||
// is available
|
||
//
|
||
|
||
pOutBufTail = pGIFBufEnd;
|
||
|
||
if (CurCode == NextCode) {
|
||
|
||
*--pOutBufTail = (BYTE)FinalChar;
|
||
CurCode = OldCode;
|
||
|
||
} else if (CurCode > NextCode) {
|
||
|
||
return(FALSE);
|
||
}
|
||
|
||
while (CurCode > MaxCol) {
|
||
|
||
if (pOutBufTail <= pOutBufHead) {
|
||
|
||
//
|
||
// Output some when buffer full
|
||
//
|
||
|
||
pfnOutputPels(pGIF2DIBInfo, (UINT)(pOutBufHead-pGIFBufBeg));
|
||
pOutBufHead = pGIFBufBeg;
|
||
}
|
||
|
||
*--pOutBufTail = *(LZWInfo.pLastChar + CurCode);
|
||
CurCode = *(LZWInfo.pPrefix + CurCode);
|
||
}
|
||
|
||
if (pOutBufTail <= pOutBufHead) {
|
||
|
||
pfnOutputPels(pGIF2DIBInfo, (UINT)(pOutBufHead - pGIFBufBeg));
|
||
pOutBufHead = pGIFBufBeg;
|
||
}
|
||
|
||
*--pOutBufTail = (BYTE)(FinalChar = CurCode);
|
||
|
||
//
|
||
// Need to move little bit, we guranteed that we minimum
|
||
// has one byte generated in this ELSE()
|
||
//
|
||
|
||
if (pOutBufTail > pOutBufHead) {
|
||
|
||
memmove(pOutBufHead,
|
||
pOutBufTail,
|
||
BytesMove = (WORD)(pGIFBufEnd - pOutBufTail));
|
||
|
||
pOutBufHead += BytesMove;
|
||
|
||
} else {
|
||
|
||
//
|
||
// We are exactly fill up the buffer, so do not need to
|
||
// move but just advance the pointer
|
||
//
|
||
|
||
pOutBufHead = pGIFBufEnd;
|
||
}
|
||
|
||
if (NextCode < MaxCode) {
|
||
|
||
*(LZWInfo.pPrefix + NextCode) = OldCode;
|
||
*(LZWInfo.pLastChar + NextCode) = (BYTE)(FinalChar = CurCode);
|
||
OldCode = LZWInfo.GetCodeRet;
|
||
}
|
||
|
||
if ((++NextCode >= MaxCode) &&
|
||
(LZWInfo.CodeSize < MAXBITS)) {
|
||
|
||
++LZWInfo.CodeSize;
|
||
MaxCode <<= 1;
|
||
LZWInfo.CSMask = (SHORT)(MaxCode - 1);
|
||
}
|
||
}
|
||
}
|
||
|
||
if (pOutBufHead > pGIFBufBeg) {
|
||
|
||
pfnOutputPels(pGIF2DIBInfo, (UINT)(pOutBufHead - pGIFBufBeg));
|
||
pOutBufHead = pGIFBufBeg;
|
||
}
|
||
|
||
return(TRUE);
|
||
}
|
||
|
||
|
||
|
||
VOID
|
||
Output8BPP(
|
||
PGIF2DIBINFO pGIF2DIBInfo,
|
||
UINT TotalPels
|
||
)
|
||
{
|
||
GIF2DIBINFO GIF2DIBInfo;
|
||
LPBYTE pGIFBuf;
|
||
UINT CopySize;
|
||
|
||
|
||
GIF2DIBInfo = *pGIF2DIBInfo;
|
||
pGIFBuf = GIF2DIBInfo.pGIFBuf;
|
||
|
||
while (TotalPels) {
|
||
|
||
CopySize = (TotalPels > (UINT)GIF2DIBInfo.RemainXPels) ?
|
||
(UINT)GIF2DIBInfo.RemainXPels : TotalPels;
|
||
|
||
CopyMemory(GIF2DIBInfo.pDIBNow, pGIFBuf, CopySize);
|
||
|
||
GIF2DIBInfo.pDIBNow += CopySize;
|
||
pGIFBuf += CopySize;
|
||
TotalPels -= CopySize;
|
||
|
||
if (!(GIF2DIBInfo.RemainXPels -= (WORD)CopySize)) {
|
||
|
||
SET_NEXT_DIB_PBUF;
|
||
}
|
||
}
|
||
|
||
*pGIF2DIBInfo = GIF2DIBInfo;
|
||
}
|
||
|
||
|
||
|
||
VOID
|
||
Output4BPP(
|
||
PGIF2DIBINFO pGIF2DIBInfo,
|
||
UINT TotalPels
|
||
)
|
||
{
|
||
GIF2DIBINFO GIF2DIBInfo;
|
||
LPBYTE pGIFBuf;
|
||
UINT CopySize;
|
||
|
||
|
||
GIF2DIBInfo = *pGIF2DIBInfo;
|
||
pGIFBuf = GIF2DIBInfo.pGIFBuf;
|
||
|
||
|
||
while (TotalPels) {
|
||
|
||
CopySize = (TotalPels > (UINT)GIF2DIBInfo.RemainXPels) ?
|
||
(UINT)GIF2DIBInfo.RemainXPels : TotalPels;
|
||
|
||
TotalPels -= (WORD)CopySize;
|
||
GIF2DIBInfo.RemainXPels -= (WORD)CopySize;
|
||
|
||
while (CopySize--) {
|
||
|
||
if (GIF2DIBInfo.PelMask ^= 0x01) {
|
||
|
||
*GIF2DIBInfo.pDIBNow++ |= (BYTE)(*pGIFBuf++ & 0x0f);
|
||
|
||
} else {
|
||
|
||
*GIF2DIBInfo.pDIBNow = (BYTE)(*pGIFBuf++ << 4);
|
||
}
|
||
}
|
||
|
||
if (!GIF2DIBInfo.RemainXPels) {
|
||
|
||
SET_NEXT_DIB_PBUF;
|
||
}
|
||
}
|
||
|
||
*pGIF2DIBInfo = GIF2DIBInfo;
|
||
}
|
||
|
||
|
||
|
||
|
||
VOID
|
||
Output1BPP(
|
||
PGIF2DIBINFO pGIF2DIBInfo,
|
||
UINT TotalPels
|
||
)
|
||
{
|
||
GIF2DIBINFO GIF2DIBInfo;
|
||
LPBYTE pGIFBuf;
|
||
UINT CopySize;
|
||
BYTE bPel;
|
||
|
||
|
||
GIF2DIBInfo = *pGIF2DIBInfo;
|
||
pGIFBuf = GIF2DIBInfo.pGIFBuf;
|
||
|
||
|
||
while (TotalPels) {
|
||
|
||
CopySize = (TotalPels > (UINT)GIF2DIBInfo.RemainXPels) ?
|
||
(UINT)GIF2DIBInfo.RemainXPels : TotalPels;
|
||
|
||
TotalPels -= CopySize;
|
||
GIF2DIBInfo.RemainXPels -= (WORD)CopySize;
|
||
|
||
bPel = (BYTE)((GIF2DIBInfo.PelMask) ? *GIF2DIBInfo.pDIBNow : 0);
|
||
|
||
while (CopySize--) {
|
||
|
||
bPel = (BYTE)((bPel << 1) | ((*pGIFBuf++) & 0x01));
|
||
|
||
if (++GIF2DIBInfo.PelMask == 8) {
|
||
|
||
*GIF2DIBInfo.pDIBNow++ = bPel;
|
||
bPel = 0;
|
||
GIF2DIBInfo.PelMask = 0;
|
||
|
||
}
|
||
}
|
||
|
||
if (GIF2DIBInfo.PelMask) {
|
||
|
||
*(GIF2DIBInfo.pDIBNow) = bPel;
|
||
}
|
||
|
||
if (!GIF2DIBInfo.RemainXPels) {
|
||
|
||
SET_NEXT_DIB_PBUF;
|
||
}
|
||
}
|
||
|
||
*pGIF2DIBInfo = GIF2DIBInfo;
|
||
}
|
||
|
||
|
||
|
||
HANDLE
|
||
ReadGIFFile(
|
||
HANDLE hFile
|
||
)
|
||
{
|
||
static SHORT NotInterleaved[] = { 0, 1, -1, -1};
|
||
static SHORT Interleaved[] = { 0, 8, 4, 8, 2, 4, 1, 2, -1, -1};
|
||
PFNOUTPUTPELS pfnOutputPels;
|
||
LPBYTE pLZWBuf;
|
||
LPBYTE pDIB;
|
||
HANDLE hDIB;
|
||
PGIFRGB pGIFRGB;
|
||
RGBQUAD FAR *pRGBQUAD;
|
||
GIFHEADER GIFHeader;
|
||
BITMAPINFOHEADER biGIF;
|
||
GIF2DIBINFO GIF2DIBInfo;
|
||
DWORD cbRead;
|
||
DWORD GIFPalSize;
|
||
WORD BitCount;
|
||
WORD ColorCount;
|
||
WORD Loop;
|
||
BOOL Ok = TRUE;
|
||
BYTE Seperator;
|
||
BYTE iFlags;
|
||
|
||
|
||
|
||
SetFilePointer(hFile, 0, NULL, FILE_BEGIN);
|
||
|
||
if ((!ReadFile(hFile, &GIFHeader, sizeof(GIFHEADER), &cbRead, NULL)) ||
|
||
(cbRead != sizeof(GIFHEADER)) ||
|
||
(strncmp(GIFHeader.Signature, "GIF", 3))) {
|
||
|
||
return(NULL); // non-gif
|
||
}
|
||
|
||
biGIF.biSize = sizeof(BITMAPINFOHEADER);
|
||
biGIF.biWidth = (DWORD)(GIF2DIBInfo.cx = (WORD)GIFHeader.Width);
|
||
biGIF.biHeight = (DWORD)(GIF2DIBInfo.cy = (WORD)GIFHeader.Height);
|
||
biGIF.biPlanes = 1;
|
||
BitCount =
|
||
biGIF.biBitCount = (WORD)((GIFHeader.Flags & 0x07) + 1);
|
||
biGIF.biCompression = (DWORD)BI_RGB;
|
||
biGIF.biXPelsPerMeter = 0;
|
||
biGIF.biYPelsPerMeter = 0;
|
||
|
||
if (BitCount == 1) {
|
||
|
||
pfnOutputPels = Output1BPP;
|
||
|
||
} else if (BitCount <= 4) {
|
||
|
||
pfnOutputPels = Output4BPP;
|
||
biGIF.biBitCount = 4;
|
||
|
||
} else if (BitCount <= 8) {
|
||
|
||
pfnOutputPels = Output8BPP;
|
||
biGIF.biBitCount = 8;
|
||
|
||
} else {
|
||
|
||
return(NULL);
|
||
}
|
||
|
||
|
||
biGIF.biClrUsed =
|
||
biGIF.biClrImportant = (DWORD)1 << biGIF.biBitCount;
|
||
|
||
GIFPalSize = (DWORD)sizeof(RGBQUAD) * (DWORD)biGIF.biClrUsed;
|
||
GIF2DIBInfo.cxBytes = (WORD)ALIGN_BPP_DW(GIF2DIBInfo.cx,
|
||
biGIF.biBitCount);
|
||
|
||
biGIF.biSizeImage = (DWORD)GIF2DIBInfo.cxBytes * (DWORD)GIF2DIBInfo.cy;
|
||
|
||
if (!(hDIB = GlobalAlloc(GHND, (DWORD)sizeof(BITMAPINFOHEADER) +
|
||
GIFPalSize + (DWORD)biGIF.biSizeImage))) {
|
||
|
||
return(NULL);
|
||
}
|
||
|
||
GIF2DIBInfo.SizeGIFBuf = (DWORD)SIZE_GIF_BUF;
|
||
|
||
if (!(GIF2DIBInfo.pGIFBuf = (LPBYTE)LocalAlloc(LPTR,
|
||
GIF2DIBInfo.SizeGIFBuf))) {
|
||
|
||
GlobalFree(hDIB);
|
||
return(NULL); // no memory for decompress
|
||
}
|
||
|
||
if (!(pLZWBuf = (LPBYTE)LocalAlloc(LPTR, SIZE_LZW_BUFS))) {
|
||
|
||
GlobalFree(hDIB);
|
||
LocalFree((HANDLE)GIF2DIBInfo.pGIFBuf);
|
||
return(NULL);
|
||
}
|
||
|
||
pDIB = GlobalLock(hDIB);
|
||
*(LPBITMAPINFOHEADER)pDIB = biGIF;
|
||
|
||
if (GIFHeader.Flags & GIFH_GLOBAL_COLOR_TABLE) {
|
||
|
||
ColorCount = (WORD)(1 << BitCount);
|
||
|
||
pGIFRGB = (PGIFRGB)(pDIB + sizeof(BITMAPINFOHEADER) +
|
||
((sizeof(RGBQUAD) - sizeof(GIFRGB)) * ColorCount));
|
||
|
||
pRGBQUAD = (RGBQUAD FAR *)(pDIB + sizeof(BITMAPINFOHEADER));
|
||
|
||
if ((!ReadFile(hFile,
|
||
pGIFRGB,
|
||
sizeof(GIFRGB) * ColorCount,
|
||
&cbRead,
|
||
NULL)) ||
|
||
(cbRead != sizeof(GIFRGB) * ColorCount)) {
|
||
|
||
Ok = FALSE;
|
||
|
||
} else {
|
||
|
||
for (Loop = 0; Loop < ColorCount; Loop++) {
|
||
|
||
pRGBQUAD->rgbRed = pGIFRGB->Red;
|
||
pRGBQUAD->rgbGreen = pGIFRGB->Green;
|
||
pRGBQUAD->rgbBlue = pGIFRGB->Blue;
|
||
pRGBQUAD->rgbReserved = 0;
|
||
|
||
++pRGBQUAD;
|
||
++pGIFRGB;
|
||
}
|
||
|
||
if (Loop = (WORD)(biGIF.biClrUsed - ColorCount)) {
|
||
|
||
ZeroMemory((LPVOID)pRGBQUAD, Loop * sizeof(RGBQUAD));
|
||
}
|
||
}
|
||
}
|
||
|
||
if ((!Ok) ||
|
||
(!ReadFile(hFile, &Seperator, sizeof(Seperator), &cbRead, NULL)) ||
|
||
(cbRead != sizeof(Seperator)) ||
|
||
(!ReadFile(hFile,
|
||
&(GIF2DIBInfo.Map),
|
||
sizeof(GIFMAP),
|
||
&cbRead,
|
||
NULL)) ||
|
||
(cbRead != sizeof(GIFMAP)) ||
|
||
(!ReadFile(hFile, &iFlags, sizeof(iFlags), &cbRead, NULL)) ||
|
||
(cbRead != sizeof(iFlags))) {
|
||
|
||
Ok = FALSE;
|
||
|
||
} else {
|
||
|
||
GIF2DIBInfo.pLineIncVec = (LPSHORT)((iFlags & GIFMAP_INTERLACE) ?
|
||
Interleaved : NotInterleaved);
|
||
GIF2DIBInfo.Map.CurY = *(GIF2DIBInfo.pLineIncVec++);
|
||
GIF2DIBInfo.Map.CurX = 0;
|
||
GIF2DIBInfo.PelMask =
|
||
GIF2DIBInfo.LinesDone = 0;
|
||
GIF2DIBInfo.RemainXPels = GIF2DIBInfo.cx;
|
||
GIF2DIBInfo.pDIBLine1 =
|
||
GIF2DIBInfo.pDIBCurLine =
|
||
GIF2DIBInfo.pDIBNow = pDIB +
|
||
(DWORD)sizeof(BITMAPINFOHEADER) +
|
||
(DWORD)GIFPalSize +
|
||
((DWORD)(GIF2DIBInfo.cy - 1) *
|
||
(DWORD)GIF2DIBInfo.cxBytes);
|
||
|
||
Ok = DeCompressGIFFileToDIB(hFile,
|
||
&GIF2DIBInfo,
|
||
pLZWBuf,
|
||
pfnOutputPels,
|
||
BitCount);
|
||
}
|
||
|
||
LocalFree((HANDLE)GIF2DIBInfo.pGIFBuf);
|
||
LocalFree((HANDLE)pLZWBuf);
|
||
GlobalUnlock(hDIB);
|
||
|
||
if (!Ok) {
|
||
|
||
GlobalFree(hDIB);
|
||
hDIB = NULL;
|
||
}
|
||
|
||
return(hDIB);
|
||
}
|