主要方法:
1. 加载图像及读取参数
FreeImage_Load
FreeImage_GetWidth
FreeImage_GetHeight
FreeImage_Allocate
FreeImage_GetPixelColor
FreeImage_SetPixelColor
2. 保存GIF
FreeImage_OpenMultiBitmap
FreeImage_SetMetadata
FreeImage_SetTagXX
FreeImage_AppendPage
3. GIF 透明模板
FreeImage_ColorQuantize
FreeImage_GetPalette
FreeImage_SetTransparencyTable
这里需要注意的是,图像通道32位转24位时,不使用FreeImage_ConvertTo24Bits,而通过PNG透明通道进行数据复制,避免背景对后面生成透明表(FreeImage _SetTransparencyTable)造成干扰。此外,注意设置24位图的背景色,避免与表情区域颜色相近。
这里做了如下设置
src_color.rgbRed = 0;
src_color.rgbBlue = 255;
src_color.rgbGreen = 0;
完整代码:
#include "FreeImagePlus.h"
#include <iostream>
using namespace std;
FIBITMAP* genhDIB8bpp(FIBITMAP* hDIB32bpp);
int main(int argc, char** argv[])
{
FreeImage_Initialise(TRUE);
// load source images
FIBITMAP* hdib1 = FreeImage_Load(FIF_PNG, "img1.png", PNG_IGNOREGAMMA);
FIBITMAP* hdib2 = FreeImage_Load(FIF_PNG, "img2.png", PNG_IGNOREGAMMA);
FIBITMAP* hdib3 = FreeImage_Load(FIF_PNG, "img3.png", PNG_IGNOREGAMMA);
if (NULL == hdib1 || NULL == hdib2 || NULL == hdib3)
{
cout << " load image(png) error.
";
return -1;
}
int bpp1 = FreeImage_GetBPP(hdib1);
int bpp2 = FreeImage_GetBPP(hdib2);
int bpp3 = FreeImage_GetBPP(hdib3);
int dib_type = FreeImage_GetImageType(hdib1);
cout << "Type: " << dib_type << " " << FIT_BITMAP << endl;
cout << "BPP: " << bpp1 << " " << bpp2 << " " << bpp3 << endl;
if (32 != bpp1 || 32 != bpp2 || 32 != bpp3)
return -1;
bool bMemoryCache = TRUE;
FIMULTIBITMAP *multi = FreeImage_OpenMultiBitmap(FIF_GIF, "out.gif", TRUE, FALSE);
int fps = 3;
DWORD dwFrameTime = (DWORD)((1000.0f / fps) + 0.5f);
cout << "gen hDIB8bpp " << endl;
FIBITMAP* dib[3];
dib[0] = genhDIB8bpp(hdib1);
dib[1] = genhDIB8bpp(hdib2);
dib[2] = genhDIB8bpp(hdib3);
cout << "AppendPage" << endl;
for (int i = 0; i < 3; i++ ){
// clear any animation metadata used by this dib as we’ll adding our own ones
FreeImage_SetMetadata(FIMD_ANIMATION, dib[i], NULL, NULL);
// add animation tags to dib[i]
FITAG *tag = FreeImage_CreateTag();
if (tag) {
FreeImage_SetTagKey(tag, "FrameTime");
FreeImage_SetTagType(tag, FIDT_LONG);
FreeImage_SetTagCount(tag, 1);
FreeImage_SetTagLength(tag, 4);
FreeImage_SetTagValue(tag, &dwFrameTime);
FreeImage_SetMetadata(FIMD_ANIMATION, dib[i], FreeImage_GetTagKey(tag), tag);
FreeImage_DeleteTag(tag);
}
FreeImage_AppendPage(multi, dib[i]);
// FreeImage_Unload(dib[i]);
}
FreeImage_CloseMultiBitmap(multi);
FreeImage_Unload(dib[0]);
FreeImage_Unload(dib[1]);
FreeImage_Unload(dib[2]);
FreeImage_Unload(hdib1);
FreeImage_Unload(hdib2);
FreeImage_Unload(hdib3);
FreeImage_DeInitialise();
return 0;
}
FIBITMAP* genhDIB8bpp(FIBITMAP* hDIB32bpp)
{
FIBITMAP* hDIB8bpp = NULL;
int w = FreeImage_GetWidth(hDIB32bpp);
int h = FreeImage_GetHeight(hDIB32bpp);
// FIBITMAP *hDIB24bpp = FreeImage_ConvertTo24Bits(hDIB32bpp);
FIBITMAP *hDIB24bpp = FreeImage_Allocate(w, h, 24);
for (int i = h - 1; i >= 0; i--)
for (int j = 0; j < w; j++)
{
RGBQUAD src_color;
FreeImage_GetPixelColor(hDIB32bpp, j, i, &src_color);
if ( 255 == src_color.rgbReserved )
FreeImage_SetPixelColor(hDIB24bpp, j, i, &src_color);
else
{
src_color.rgbRed = 0;
src_color.rgbBlue = 255; src_color.rgbGreen = 0;
FreeImage_SetPixelColor(hDIB24bpp, j, i, &src_color);
}
}
FreeImage_Save(FIF_JPEG, hDIB24bpp, "out.jpg");
BYTE Transparency[256];
if (!hDIB8bpp)
hDIB8bpp = FreeImage_ColorQuantize(hDIB24bpp, FIQ_WUQUANT);
RGBQUAD *Palette = FreeImage_GetPalette(hDIB8bpp);
for (int i = 0; i < 256; i++)
{
Transparency[i] = 0xFF;
if (Palette[i].rgbRed != 0x00 && Palette[i].rgbBlue != 0xFF && Palette[i].rgbGreen > 0x00)
{
Transparency[i] = 0x00;
}
}
FreeImage_SetTransparencyTable(hDIB8bpp, Transparency, 256);
// FreeImage_Save(FIF_PNG, hDIB8bpp, "out.png");
FreeImage_Unload(hDIB24bpp);
return hDIB8bpp;
}
原图:
结果:
眉毛缺失眉毛完整