Leaked source code of windows server 2003
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 
 
 

754 lines
23 KiB

/*++
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);
}