你可以用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; }
GDI+我也测试过了转换成的GIF不行,比用ACDSEE转换的效果差很多!
http://www.codeproject.com/bitmap/cximage.asp
cximage太庞大了,阅读起来太困难
最简单的莫过于CImage或graphics了。
TO: taianmonkey() cximage我也测试过了不行!转换成的GIF是分成很多小块的,没法看!
*
* 函数名称:
* 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);
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;
}
*
* 函数名称:
* 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)
对于色深>256bit的如何转换?
如果没有的话下载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;
}
GDI+可以把24位真彩的BMP转成GIF,但是都成了256位的了,颜色很难看,为什么?
GIF是只有256色,但是用AcdSee转成的Gif就非常好看,难道AcdSee有什么专利算法可以在转化的时候进行色彩上的优化?用GDI+转的就好像缺了某些颜色一样。
能否给个例子?
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;
}
cximage我也测试过了不行!转换成的GIF是分成很多小块的,没法看!