FreeImage 生成带透明通道的GIF

主要方法:
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. \n";
        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;
}

原图:
这里写图片描述这里写图片描述这里写图片描述
结果:
眉毛缺失这里写图片描述眉毛完整这里写图片描述

  • 1
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
FreeImage是一个开源的图像处理库,支持多种图像格式的读取、处理和输出。如果想要使用FreeImage库来缩放GIF图片,可以按照以下步骤操作: 1.加载GIF图片 使用FreeImage_LoadMultiBitmapFromHandle函数加载GIF文件,并获取GIF文件中所有的帧信息,如下所示: ```c++ FIMULTIBITMAP* pMultiBitmap = FreeImage_LoadMultiBitmapFromHandle(FIF_GIF, hMem, GIF_PLAYBACK); ``` 在上述代码中,hMem是指向GIF文件内存块的指针,GIF_PLAYBACK是指定GIF文件的播放方式(循环或单次)。 2.缩放GIF图片 使用FreeImage_Rescale函数对GIF文件中的每帧进行缩放,如下所示: ```c++ for (int i = 0; i < FreeImage_GetPageCount(pMultiBitmap); i++) { FIBITMAP* pBitmap = FreeImage_LockPage(pMultiBitmap, i); FIBITMAP* pScaledBitmap = FreeImage_Rescale(pBitmap, newWidth, newHeight, FILTER_BICUBIC); FreeImage_UnlockPage(pMultiBitmap, pBitmap, FALSE); FreeImage_Unload(pBitmap); FreeImage_Save(FIF_GIF, pScaledBitmap, "output.gif", GIF_PLAYBACK); FreeImage_Unload(pScaledBitmap); } ``` 在上述代码中,newWidth和newHeight分别代表缩放后的宽度和高度,FILTER_BICUBIC表示使用Bicubic滤波器进行缩放。 3.保存GIF图片 使用FreeImage_Save函数将缩放后的GIF文件保存到磁盘中,如下所示: ```c++ FreeImage_Save(FIF_GIF, pMultiBitmap, "output.gif", GIF_PLAYBACK); ``` 在上述代码中,pMultiBitmap是指向GIF文件的指针。 完整的代码示例: ```c++ #include <iostream> #include "FreeImage.h" int main() { // 加载GIF图片 FILE* fp = fopen("input.gif", "rb"); fseek(fp, 0, SEEK_END); long lSize = ftell(fp); rewind(fp); BYTE* pBuffer = new BYTE[lSize]; fread(pBuffer, lSize, 1, fp); fclose(fp); FIMEMORY* hMem = FreeImage_OpenMemory(pBuffer, lSize); FIMULTIBITMAP* pMultiBitmap = FreeImage_LoadMultiBitmapFromHandle(FIF_GIF, hMem, GIF_PLAYBACK); // 缩放GIF图片 int newWidth = 200; int newHeight = 200; for (int i = 0; i < FreeImage_GetPageCount(pMultiBitmap); i++) { FIBITMAP* pBitmap = FreeImage_LockPage(pMultiBitmap, i); FIBITMAP* pScaledBitmap = FreeImage_Rescale(pBitmap, newWidth, newHeight, FILTER_BICUBIC); FreeImage_UnlockPage(pMultiBitmap, pBitmap, FALSE); FreeImage_Unload(pBitmap); FreeImage_Save(FIF_GIF, pScaledBitmap, "output.gif", GIF_PLAYBACK); FreeImage_Unload(pScaledBitmap); } // 保存GIF图片 FreeImage_Save(FIF_GIF, pMultiBitmap, "output.gif", GIF_PLAYBACK); // 释放内存 FreeImage_CloseMemory(hMem); delete[] pBuffer; FreeImage_CloseMultiBitmap(pMultiBitmap); return 0; } ``` 需要注意的是,使用FreeImage库需要在系统中预先安装,并在C++项目中添加FreeImage.h和FreeImage.lib文件。此外,FreeImage库支持的图像格式较多,可根据需要选择合适的图像格式进行缩放。
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值