如题

解决方案 »

  1.   

    /*************************************************************************
     *
     * 函数名称:
     *   DIBToGIF()
     *
     * 参数:
     *   LPSTR lpDIB        - 指向DIB对象的指针
     *   CFile& file        - 要保存的文件
     *   BOOL bInterlace - 是否按照交错方式保存
     *
     * 返回值:
     *   BOOL               - 成功返回True,否则返回False。
     *
     * 说明:
     *   该函数将指定的DIB对象(< 256色)保存为GIF文件。
     *
     *************************************************************************/
    BOOL WINAPI DIBToGIF(LPSTR lpDIB, CFile& file, BOOL bInterlace)
    {
    // 循环变量
    WORD i;
    WORD j;

    // DIB高度
    WORD wHeight;

    // DIB宽度
    WORD wWidth;

    // 指向DIB象素指针
    LPSTR   lpDIBBits;

    // GIF文件头
    GIFHEADER          GIFH;

    // GIF逻辑屏幕描述块
    GIFSCRDESC         GIFS;

    // GIF图像描述块
    GIFIMAGE           GIFI;

    // GIF编码参数
    GIFC_VAR           GIFCVar;

    // 颜色数目
    WORD               wColors;

    // 每行字节数
    WORD               wWidthBytes;

    // 调色板
    BYTE               byGIF_Pal[768];

    // 字节变量
    BYTE               byChar;

    // 指向BITMAPINFO结构的指针(Win3.0)
    LPBITMAPINFO    lpbmi;

    // 指向BITMAPCOREINFO结构的指针
    LPBITMAPCOREINFO   lpbmc;

    // 表明是否是Win3.0 DIB的标记
    BOOL    bWinStyleDIB;

    // 获取DIB高度
    wHeight = (WORD) DIBHeight(lpDIB);

    // 获取DIB宽度
    wWidth  = (WORD) DIBWidth(lpDIB);

    // 找到DIB图像象素起始位置
             //你可以根据图像头、信息头来进行定位
             //从而替代该函数
    lpDIBBits = FindDIBBits(lpDIB);

    // 给GIFCVar结构赋值
    GIFCVar.wWidth     = wWidth;
    GIFCVar.wDepth     = wHeight;
    GIFCVar.wBits      = DIBBitCount(lpDIB);//位元深度,可从图像信息头获得
    GIFCVar.wLineBytes = (WORD)BYTE_WBYTES((DWORD)GIFCVar.wWidth *
       (DWORD)GIFCVar.wBits);

    // 计算每行字节数
    wWidthBytes = (WORD)DWORD_WBYTES(wWidth * (DWORD)GIFCVar.wBits);

    // 计算颜色数目
    wColors     = 1 << GIFCVar.wBits;

    // 获取指向BITMAPINFO结构的指针(Win3.0)
    lpbmi = (LPBITMAPINFO)lpDIB;

    // 获取指向BITMAPCOREINFO结构的指针
    lpbmc = (LPBITMAPCOREINFO)lpDIB;

    // 判断是否是WIN3.0的DIB
    bWinStyleDIB = IS_WIN30_DIB(lpDIB);

    // 给调色板赋值
    if (bWinStyleDIB)
    {
    j = 0;
    for (i = 0; i < wColors; i++)
    {
    // 读取红色分量
    byGIF_Pal[j++] = lpbmi->bmiColors[i].rgbRed;

    // 读取绿色分量
    byGIF_Pal[j++] = lpbmi->bmiColors[i].rgbGreen;

    // 读取蓝色分量
    byGIF_Pal[j++] = lpbmi->bmiColors[i].rgbBlue;
    }
    }
    else
    {
    j = 0;
    for (i = 0; i < wColors; i++)
    {
    // 读取红色分量
    byGIF_Pal[j++] = lpbmc->bmciColors[i].rgbtRed;

    // 读取绿色分量
    byGIF_Pal[j++] = lpbmc->bmciColors[i].rgbtGreen;

    // 读取红色分量
    byGIF_Pal[j++] = lpbmc->bmciColors[i].rgbtBlue;
    }
    }

    ////////////////////////////////////////////////////////////////////////////////////////
    // 开始写GIF文件

    // 写GIF文件头
    GIFH.bySignature[0] = 'G';
    GIFH.bySignature[1] = 'I';
    GIFH.bySignature[2] = 'F';
    GIFH.byVersion[0]='8';
    GIFH.byVersion[1]='9';
    GIFH.byVersion[2]='a';
    file.Write((LPSTR)&GIFH, 6);

    // 写GIF逻辑屏幕描述块
    GIFS.wWidth               = GIFCVar.wWidth;
    GIFS.wDepth               = GIFCVar.wDepth;
    GIFS.GlobalFlag.PalBits   = (BYTE)(GIFCVar.wBits - 1);
    GIFS.GlobalFlag.SortFlag  = 0x00;
    GIFS.GlobalFlag.ColorRes  = (BYTE)(GIFCVar.wBits - 1);
    GIFS.GlobalFlag.GlobalPal = 0x01;
    GIFS.byBackground         = 0x00;
    GIFS.byAspect             = 0x00;
    file.Write((LPSTR)&GIFS, 7);

    // 写GIF全局调色板
    file.Write((LPSTR)byGIF_Pal,(wColors*3));

    // 写GIF图像描述间隔符
    byChar      = 0x2C;
    file.Write((LPSTR)&byChar,1);

    // 写GIF图像描述块
    GIFI.wLeft                = 0;
    GIFI.wTop                 = 0;
    GIFI.wWidth               = GIFCVar.wWidth;
    GIFI.wDepth               = GIFCVar.wDepth;
    GIFI.LocalFlag.PalBits    = 0x00;
    GIFI.LocalFlag.Reserved   = 0x00;
    GIFI.LocalFlag.SortFlag   = 0x00;
    GIFI.LocalFlag.Interlace  = (BYTE)(bInterlace ? 0x01 : 0x00);
    GIFI.LocalFlag.LocalPal   = 0x00;
    file.Write((LPSTR)&GIFI, 9);

    // 写GIF图像压缩数据
    HANDLE hSrcBuff = GlobalAlloc(GHND,(DWORD)MAX_BUFF_SIZE);
    GIFCVar.lpDataBuff = (LPSTR)GlobalLock(hSrcBuff);
    GIFCVar.lpEndBuff  = GIFCVar.lpDataBuff;
    GIFCVar.dwTempCode = 0UL;
    GIFCVar.wByteCnt   = 0;
    GIFCVar.wBlockNdx  = 1;
    GIFCVar.byLeftBits = 0x00;

    // 进行GIF_LZW编码
    EncodeGIF_LZW(lpDIBBits, file, &GIFCVar,wWidthBytes, bInterlace);

    // 判断是否编码成功
    if (GIFCVar.wByteCnt)
    {
    // 写入文件
    file.Write(GIFCVar.lpDataBuff, GIFCVar.wByteCnt);
    }

    // 释放内存
    GlobalUnlock(hSrcBuff);
    GlobalFree(hSrcBuff);

    // 写GIF Block Terminator
    byChar   = 0x00;
    file.Write((LPSTR)&byChar,1);

    // 写GIF文件结尾块
    byChar   = 0x3B;
    file.Write((LPSTR)&byChar,1);

    // 返回
    return TRUE;
    }/*************************************************************************
     *
     * 函数名称:
     *   EncodeGIF_LZW()
     *
     * 参数:
     *   LPSTR lpDIBBits - 指向源DIB图像指针
     *   CFile& file - 要保存的文件
     *   LPGIFC_VAR lpGIFCVar - 指向GIFC_VAR结构的指针
     *  WORD wWidthBytes - 每行图像字节数
     *  BOOL bInterlace - 是否按照交错方式保存
     *
     * 返回值:
     *   无
     *
     * 说明:
     *   该函数对指定图像进行GIF_LZW编码。
     *
     *************************************************************************/
    void WINAPI EncodeGIF_LZW(LPSTR lpDIBBits, CFile& file, 
      LPGIFC_VAR lpGIFCVar,WORD wWidthBytes, BOOL bInterlace)
    {
    // 内存分配句柄
    HANDLE hTableNdx;
    HANDLE hPrefix;
    HANDLE hSuffix;

    // 指向字串表指针
    LPWORD lpwTableNdx;

    // 用于字串表搜索的索引
    LPWORD lpwPrefix;
    LPBYTE lpbySuffix;

    // 指向当前编码像素的指针
    LPSTR  lpImage;

    // 计算当前数据图像的偏移量
    DWORD  dwDataNdx;

    // LZW_CLEAR
    WORD   wLZW_CLEAR;

    // LZW_EOI
    WORD   wLZW_EOI;

    // LZW_MinCodeLen
    BYTE   byLZW_MinCodeLen;

    // 字串表索引
    WORD   wPreTableNdx;
    WORD   wNowTableNdx;
    WORD   wTopTableNdx;

    // 哈希表索引
    WORD   wHashNdx;
    WORD   wHashGap;
    WORD   wPrefix;
    WORD   wShiftBits;

    // 当前图像的行数
    WORD   wRowNum;

    WORD   wWidthCnt;

    // 循环变量
    WORD   wi;
    WORD   wj;

    // 交错方式存储时每次增加的行数
    WORD   wIncTable[5]  = { 8,8,4,2,0 }; 

    // 交错方式存储时起始行数
    WORD   wBgnTable[5]  = { 0,4,2,1,0 }; 

    BOOL   bStart;
    BYTE   bySuffix;
    BYTE   bySubBlock[256];
    BYTE   byCurrentBits;
    BYTE   byMask;
    BYTE   byChar;
    BYTE   byPass;

    // 临时字节变量
    BYTE   byTemp;

    // 给字串表分配内存
    hTableNdx        = GlobalAlloc(GHND,(DWORD)(MAX_HASH_SIZE<<1));
    hPrefix          = GlobalAlloc(GHND,(DWORD)(MAX_HASH_SIZE<<1));
    hSuffix          = GlobalAlloc(GHND,(DWORD)MAX_HASH_SIZE);

    // 锁定内存
    lpwTableNdx      = (LPWORD)GlobalLock(hTableNdx);
    lpwPrefix        = (LPWORD)GlobalLock(hPrefix);
    lpbySuffix       = (LPBYTE)GlobalLock(hSuffix);

      

  2.   

    // 计算LZW_MinCodeLen
    byLZW_MinCodeLen = (BYTE)((lpGIFCVar->wBits>1) ? lpGIFCVar->wBits : 0x02);

    // 写GIF LZW最小代码大小
    file.Write((LPSTR)&byLZW_MinCodeLen,1);

    wRowNum          = 0;
    bStart           = TRUE;
    byPass           = 0x00;

    // 计算LZW_CLEAR
    wLZW_CLEAR       = 1 << byLZW_MinCodeLen;

    // 计算LZW_EOI
    wLZW_EOI         = wLZW_CLEAR + 1;

    // 初始化字串表
    byCurrentBits    = byLZW_MinCodeLen + (BYTE)0x01;
    wNowTableNdx     = wLZW_CLEAR + 2;
    wTopTableNdx     = 1 << byCurrentBits;
    for(wi=0; wi<MAX_HASH_SIZE; wi++)
    {
    // 初始化为0xFFFF
    *(lpwTableNdx+wi) = 0xFFFF;
    }

    // 输出LZW_CLEAR
    GIF_LZW_WriteCode(file, wLZW_CLEAR, (LPSTR)bySubBlock,
      &byCurrentBits, lpGIFCVar);

    // 逐行编码
    for(wi=0; wi<lpGIFCVar->wDepth; wi++)
    {
    // 计算当前偏移量
    dwDataNdx  = (DWORD)(lpGIFCVar->wDepth - 1 - wRowNum) * (DWORD)wWidthBytes;

    // 指向当前行图像的指针
    lpImage    = (LPSTR) (((BYTE*)lpDIBBits) + dwDataNdx);

    wWidthCnt  = 0;
    wShiftBits = 8 - lpGIFCVar->wBits;
    byMask     = (BYTE)((lpGIFCVar->wBits==1) ? 0x80 : 0xF0);

    if (bStart)
    {
    // 判断是否是256色位图(一个像素一字节)
    if (lpGIFCVar->wBits==8)
    {
    // 256色,直接赋值即可
    byTemp      = *lpImage++;
    }
    else
    {
    // 非256色,需要移位获取像素值
    wShiftBits  = 8 - lpGIFCVar->wBits;
    byMask      = (BYTE)((lpGIFCVar->wBits==1) ? 0x80 : 0xF0);
    byTemp      = (BYTE)((*lpImage & byMask) >> wShiftBits);
    byMask    >>= lpGIFCVar->wBits;
    wShiftBits -= lpGIFCVar->wBits;
    }
    wPrefix    = (WORD)byTemp;
    bStart     = FALSE;
    wWidthCnt ++;
    }

    // 每行编码
    while(wWidthCnt < lpGIFCVar->wWidth)
    {
    // 判断是否是256色位图(一个像素一字节)
    if (lpGIFCVar->wBits==8)
    {
    // 256色,直接赋值即可
    byTemp = *lpImage++;
    }
    else
    {
    // 非256色,需要移位获取像素值
    byChar = *lpImage;
    byTemp = (BYTE)((byChar & byMask) >> wShiftBits);
    if (wShiftBits)
    {
    byMask    >>= lpGIFCVar->wBits;
    wShiftBits -= lpGIFCVar->wBits;
    }
    else
    {
    wShiftBits  = 8 - lpGIFCVar->wBits;
    byMask      = (BYTE)((lpGIFCVar->wBits==1) ? 0x80 : 0xF0);
    lpImage    ++;
    }
    }
    bySuffix   = byTemp;
    wWidthCnt ++;

    // 查找当前字符串是否存在于字串表中
    wHashNdx = wPrefix ^ ((WORD)bySuffix << 4);
    wHashGap = (wHashNdx ? (MAX_HASH_SIZE - wHashNdx) : 1);

    // 判断当前字符串是否在字串表中
    while(TRUE)
    {
    // 当前字符串不在字串表中
    if (*(lpwTableNdx + wHashNdx) == 0xFFFF)
    {
       // 新字符串,退出循环
       break;
    }

    // 判断是否找到该字符串
    if ((*(lpwPrefix+wHashNdx)  == wPrefix) &&
    (*(lpbySuffix+wHashNdx) == bySuffix))
    {
    // 找到,退出循环
    break;
    }

    // 第二哈希表
    if (wHashNdx < wHashGap)
    {
    wHashNdx += MAX_HASH_SIZE;
    }
    wHashNdx -= wHashGap;
    }

    // 判断是否是新字符串
    if (*(lpwTableNdx+wHashNdx) != 0xFFFF)
    {
    // 不是新字符串
    wPrefix = *(lpwTableNdx + wHashNdx);
     }
     else
     {
    // 新字符串

    // 输出该编码
    GIF_LZW_WriteCode(file,wPrefix,(LPSTR)bySubBlock,
       &byCurrentBits,lpGIFCVar);

    // 将该新字符串添加到字串表中
    wPreTableNdx = wNowTableNdx;

    // 判断是否达到最大字串表大小
    if (wNowTableNdx < MAX_TABLE_SIZE)
    {
    *(lpwTableNdx+wHashNdx) = wNowTableNdx++;
    *(lpwPrefix+wHashNdx)   = wPrefix;
    *(lpbySuffix+wHashNdx)  = bySuffix;
    }

    if (wPreTableNdx == wTopTableNdx)
    {
    if (byCurrentBits<12)
    {
    byCurrentBits ++;
    wTopTableNdx <<= 1;
    }
    else
    {
    // 字串表到达最大长度

    // 输出LZW_CLEAR
    GIF_LZW_WriteCode(file, wLZW_CLEAR, (LPSTR)bySubBlock,
     &byCurrentBits,lpGIFCVar);

    // 重新初始化字串表
    byCurrentBits    = byLZW_MinCodeLen + (BYTE)0x01;
    wLZW_CLEAR       = 1 << byLZW_MinCodeLen;
    wLZW_EOI         = wLZW_CLEAR + 1;
    wNowTableNdx     = wLZW_CLEAR + 2;
    wTopTableNdx     = 1 << byCurrentBits;
    for(wj=0;wj<MAX_HASH_SIZE;wj++)
    {
    // 初始化为0xFFFF
    *(lpwTableNdx+wj) = 0xFFFF;
    }
    }
    }
    wPrefix = (WORD)bySuffix;
    }
    }

    // 判断是否是交错方式
    if (bInterlace)
    {
    // 交错方式,计算下一行位置
    wRowNum += wIncTable[byPass];
    if (wRowNum>=lpGIFCVar->wDepth)
    {
    byPass ++;
    wRowNum = wBgnTable[byPass];
    }
    }
    else
    {
    // 非交错方式,直接将行数加一即可
    wRowNum ++;
    }
    }
    // 输出当前编码
    GIF_LZW_WriteCode(file, wPrefix, (LPSTR)bySubBlock,
      &byCurrentBits,lpGIFCVar);

    // 输出LZW_EOI
    GIF_LZW_WriteCode(file,wLZW_EOI,(LPSTR)bySubBlock,
      &byCurrentBits,lpGIFCVar);

    if (lpGIFCVar->byLeftBits)
    {
    // 加入该字符
    bySubBlock[lpGIFCVar->wBlockNdx++] = (BYTE)lpGIFCVar->dwTempCode;

    // 判断是否超出MAX_SUBBLOCK_SIZE
    if (lpGIFCVar->wBlockNdx > MAX_SUBBLOCK_SIZE)
    {
    // 判断wByteCnt + 256是否超过MAX_BUFF_SIZE
    if ((lpGIFCVar->wByteCnt + 256) >= MAX_BUFF_SIZE)
    {
    // 输出
    file.Write(lpGIFCVar->lpDataBuff,
      lpGIFCVar->wByteCnt);
    lpGIFCVar->lpEndBuff = lpGIFCVar->lpDataBuff;
    lpGIFCVar->wByteCnt  = 0;
    }
    bySubBlock[0]           = (BYTE)(lpGIFCVar->wBlockNdx - 1);
    memcpy(lpGIFCVar->lpEndBuff,(LPSTR)bySubBlock,lpGIFCVar->wBlockNdx);
    lpGIFCVar->lpEndBuff   += lpGIFCVar->wBlockNdx;
    lpGIFCVar->wByteCnt    += lpGIFCVar->wBlockNdx;
    lpGIFCVar->wBlockNdx    = 1;
    }
    lpGIFCVar->dwTempCode = 0UL;
    lpGIFCVar->byLeftBits = 0x00;
    }

    if (lpGIFCVar->wBlockNdx > 1)
    {
    // 判断wByteCnt + 256是否超过MAX_BUFF_SIZE
    if ((lpGIFCVar->wByteCnt + 256) >= MAX_BUFF_SIZE)
    {
    // 输出
    file.Write(lpGIFCVar->lpDataBuff,
       lpGIFCVar->wByteCnt);
    lpGIFCVar->lpEndBuff = lpGIFCVar->lpDataBuff;
    lpGIFCVar->wByteCnt  = 0;
    }
    bySubBlock[0]           = (BYTE)(lpGIFCVar->wBlockNdx - 1);
    memcpy(lpGIFCVar->lpEndBuff,(LPSTR)bySubBlock,lpGIFCVar->wBlockNdx);
    lpGIFCVar->lpEndBuff   += lpGIFCVar->wBlockNdx;
    lpGIFCVar->wByteCnt    += lpGIFCVar->wBlockNdx;
    lpGIFCVar->wBlockNdx    = 1;
    }

    // 解除锁定
    GlobalUnlock(hTableNdx);
    GlobalUnlock(hPrefix);
    GlobalUnlock(hSuffix);

    // 释放内存
    GlobalFree(hTableNdx);
    GlobalFree(hPrefix);
    GlobalFree(hSuffix);

    // 退出
    return;
    }
      

  3.   

    /*************************************************************************
     *
     * 函数名称:
     *   GIF_LZW_WriteCode()
     *
     * 参数:
     *   CFile& file - 要保存的文件
     *  WORD wCode - 要添加的编码
     *   LPSTR lpSubBlock - 子块
     *  LPBYTE lpbyCurrentBits - 当前位数
     *  LPGIFC_VAR lpGIFCVar - 指向GIFC_VAR结构的指针
     *
     * 返回值:
     *   无
     *
     * 说明:
     *   该函数用来输出一个编码。
     *
     *************************************************************************/
    void WINAPI GIF_LZW_WriteCode(CFile& file, WORD wCode, LPSTR lpSubBlock,
                                  LPBYTE lpbyCurrentBits,LPGIFC_VAR lpGIFCVar)
    {
    // 输出该编码
    lpGIFCVar->dwTempCode |= ((DWORD)wCode << lpGIFCVar->byLeftBits);
    lpGIFCVar->byLeftBits += (*lpbyCurrentBits);

    while(lpGIFCVar->byLeftBits >= 0x08)
    {
    lpSubBlock[lpGIFCVar->wBlockNdx++] = (BYTE)lpGIFCVar->dwTempCode;
          
    // 判断是否超出MAX_SUBBLOCK_SIZE
    if (lpGIFCVar->wBlockNdx > MAX_SUBBLOCK_SIZE)
    {
    // 判断wByteCnt + 256是否超过MAX_BUFF_SIZE
    if ((lpGIFCVar->wByteCnt + 256) >= MAX_BUFF_SIZE)
    {
    // 输出
    file.Write(lpGIFCVar->lpDataBuff,
    lpGIFCVar->wByteCnt);
                lpGIFCVar->lpEndBuff = lpGIFCVar->lpDataBuff;
            lpGIFCVar->wByteCnt  = 0;
    }
    lpSubBlock[0]           = (BYTE)(lpGIFCVar->wBlockNdx - 1);
    memcpy(lpGIFCVar->lpEndBuff,lpSubBlock,lpGIFCVar->wBlockNdx);
    lpGIFCVar->lpEndBuff   += lpGIFCVar->wBlockNdx;
    lpGIFCVar->wByteCnt    += lpGIFCVar->wBlockNdx;
    lpGIFCVar->wBlockNdx    = 1;
    }
    lpGIFCVar->dwTempCode >>= 8;
    lpGIFCVar->byLeftBits  -= 0x08;
    }

    // 返回
    return;
    }
    可能用到的结构和宏定义:
    typedef struct gifheader
       {
          BYTE bySignature[3];
          BYTE byVersion[3];
       }  GIFHEADER;typedef struct gifscrdesc
       {
          WORD wWidth;
          WORD wDepth;
          struct globalflag
             {
                BYTE PalBits   : 3;
                BYTE SortFlag  : 1;
                BYTE ColorRes  : 3;
                BYTE GlobalPal : 1;
             }  GlobalFlag;
          BYTE byBackground;
          BYTE byAspect;
       }  GIFSCRDESC;typedef struct gifimage
       {
          WORD wLeft;
          WORD wTop;
          WORD wWidth;
          WORD wDepth;
          struct localflag
             {
                BYTE PalBits   : 3;
                BYTE Reserved  : 2;
                BYTE SortFlag  : 1;
                BYTE Interlace : 1;
                BYTE LocalPal  : 1;
             }  LocalFlag;
       }  GIFIMAGE;typedef struct gifcontrol
       {
          BYTE byBlockSize;
          struct flag
             {
                BYTE Transparency   : 1;
                BYTE UserInput      : 1;
                BYTE DisposalMethod : 3;
                BYTE Reserved       : 3;
             }  Flag;
          WORD wDelayTime;
          BYTE byTransparencyIndex;
          BYTE byTerminator;
       }  GIFCONTROL;typedef struct gifplaintext
       {
          BYTE byBlockSize;
          WORD wTextGridLeft;
          WORD wTextGridTop;
          WORD wTextGridWidth;
          WORD wTextGridDepth;
          BYTE byCharCellWidth;
          BYTE byCharCellDepth;
          BYTE byForeColorIndex;
          BYTE byBackColorIndex;
       }  GIFPLAINTEXT;typedef struct gifapplication
       {
          BYTE byBlockSize;
          BYTE byIdentifier[8];
          BYTE byAuthentication[3];
       }  GIFAPPLICATION;typedef struct gifd_var
       {
          LPSTR lpDataBuff;
          LPSTR lpBgnBuff;
          LPSTR lpEndBuff;
          DWORD dwDataLen;
          WORD  wMemLen;
          WORD  wWidth;
          WORD  wDepth;
          WORD  wLineBytes;
          WORD  wBits;
          BOOL  bEOF;
          BOOL  bInterlace;
       }  GIFD_VAR;
    typedef GIFD_VAR FAR *LPGIFD_VAR;typedef struct gifc_var
       {
          LPSTR lpDataBuff;
          LPSTR lpEndBuff;
          DWORD dwTempCode;
          WORD  wWidth;
          WORD  wDepth;
          WORD  wLineBytes;
          WORD  wBits;
          WORD  wByteCnt;
          WORD  wBlockNdx;
          BYTE  byLeftBits;
       }  GIFC_VAR;
    typedef GIFC_VAR FAR *LPGIFC_VAR;
    // 宏运算
    #define DWORD_WBYTES(x)         ( (((x) + 31UL) >> 5) << 2 )
    #define WORD_WBYTES(x)          ( (((x) + 15UL) >> 4) << 1 )
    #define BYTE_WBYTES(x)          (  ((x) +  7UL) >> 3       )//常量
    #define MAX_BUFF_SIZE           32768 /* 32K */
    #define MAX_HASH_SIZE            5051
    #define MAX_TABLE_SIZE           4096 /* 12-bit */
    #define MAX_SUBBLOCK_SIZE         255
    // 判断是否是Win 3.0的DIB
    #define IS_WIN30_DIB(lpbi)  ((*(LPDWORD)(lpbi)) == sizeof(BITMAPINFOHEADER))// 在计算图像大小时,采用公式:biSizeImage = biWidth' × biHeight。
    // 是biWidth',而不是biWidth,这里的biWidth'必须是4的整倍数,表示
    // 大于或等于biWidth的,离4最近的整倍数。WIDTHBYTES就是用来计算
    // biWidth'
    #define WIDTHBYTES(bits)    (((bits) + 31) / 32 * 4)
      

  4.   

    To: subtop(风歌) 
    对于色深>256bit的如何转换?
      

  5.   

    补充说明一下:要求能转换24位真彩的BMP为GIF
      

  6.   

    用GDI+
    如果没有的话下载GDI+的开发包Sample:#include <windows.h>
    #include <gdiplus.h>
    #include <stdio.h>
    using namespace Gdiplus;int GetEncoderClsid(const WCHAR* format, CLSID* pClsid)
    {
       UINT  num = 0;          // number of image encoders
       UINT  size = 0;         // size of the image encoder array in bytes   ImageCodecInfo* pImageCodecInfo = NULL;   GetImageEncodersSize(&num, &size);
       if(size == 0)
          return -1;  // Failure   pImageCodecInfo = (ImageCodecInfo*)(malloc(size));
       if(pImageCodecInfo == NULL)
          return -1;  // Failure   GetImageEncoders(num, size, pImageCodecInfo);   for(UINT j = 0; j < num; ++j)
       {
          if( wcscmp(pImageCodecInfo[j].MimeType, format) == 0 )
          {
             *pClsid = pImageCodecInfo[j].Clsid;
             free(pImageCodecInfo);
             return j;  // Success
          }    
       }   free(pImageCodecInfo);
       return -1;  // Failure
    }
    INT main()
    {
       // Initialize GDI+.
       GdiplusStartupInput gdiplusStartupInput;
       ULONG_PTR gdiplusToken;
       GdiplusStartup(&gdiplusToken, &gdiplusStartupInput, NULL);   CLSID   encoderClsid;
       Status  stat;
       Image*   image = new Image(L"Bird.bmp");   // Get the CLSID of the PNG encoder.
       GetEncoderClsid(L"image/gif", &encoderClsid);   stat = image->Save(L"Bird.gif", &encoderClsid, NULL);   if(stat == Ok)
          printf("Bird.png was saved successfully\n");
       else
          printf("Failure: stat = %d\n", stat);    delete image;
       GdiplusShutdown(gdiplusToken);
       return 0;
    }
      

  7.   

    To:hornedreaper(镰刀魔) 
    GDI+可以把24位真彩的BMP转成GIF,但是都成了256位的了,颜色很难看,为什么?
      

  8.   

    还可以使用IPicture 接口!!!!!!!!!!!
      

  9.   

    To: hornedreaper(镰刀魔) 
    GIF是只有256色,但是用AcdSee转成的Gif就非常好看,难道AcdSee有什么专利算法可以在转化的时候进行色彩上的优化?用GDI+转的就好像缺了某些颜色一样。
      

  10.   

    To:force_eagle(战鹰)
    能否给个例子?
      

  11.   

    我给你的代码完全可以把真彩色图像转化为GIF,你可以看看WINDOWS的画图板(mspaint.exe)程序,转化后的GIF全都是256色:)
      

  12.   

    你可以用GDI+做JPG、BMP、TIF、PNG、GIF间的转换,例如:
    Platform SDK: GDI+ 
    Converting a BMP Image to a PNG Image
    To save an image to a disk file, call the Save method of the Image class. The following console application loads a BMP image from a disk file, converts the image to the PNG format, and saves the converted image to a new disk file. The main function relies on the helper function GetEncoderClsid, which is shown in Retrieving the Class Identifier for an Encoder.#include <windows.h>
    #include <gdiplus.h>
    #include <stdio.h>
    using namespace Gdiplus;INT GetEncoderClsid(const WCHAR* format, CLSID* pClsid);  // helper functionINT main()
    {
       // Initialize GDI+.
       GdiplusStartupInput gdiplusStartupInput;
       ULONG_PTR gdiplusToken;
       GdiplusStartup(&gdiplusToken, &gdiplusStartupInput, NULL);   CLSID   encoderClsid;
       Status  stat;
       Image*   image = new Image(L"Bird.bmp");   // Get the CLSID of the PNG encoder.
       GetEncoderClsid(L"image/png", &encoderClsid);   stat = image->Save(L"Bird.png", &encoderClsid, NULL);   if(stat == Ok)
          printf("Bird.png was saved successfully\n");
       else
          printf("Failure: stat = %d\n", stat);    delete image;
       GdiplusShutdown(gdiplusToken);
       return 0;
    }
      

  13.   

    GDI+我也测试过了转换成的GIF不行,比用ACDSEE转换的效果差很多!
      

  14.   

    http://www.codeproject.com/bitmap/cximage.asp
      

  15.   

    cximage太庞大了,阅读起来太困难
      

  16.   

    最简单的莫过于CImage或graphics了。
      

  17.   

    TO: taianmonkey() 
    cximage我也测试过了不行!转换成的GIF是分成很多小块的,没法看!