OpenCV4 打開 gif (FreeImage)

準備

FreeImage 庫,自己編譯或下載

這裏只提供 macOS 版的靜態庫 點擊這裏下載。密碼: p2lb。

代碼:

現在僅支持讀取 CV_8UC3 / CV8UC4 的 gif 圖。

#include <opencv2/opencv.hpp>
#include "FreeImage.h"
using namespace cv;

void show_gif2(const char* path, int interval_ms) {
    // path: 文件路徑
    // interval ms:每張圖片顯示間隔
    
    FreeImage_Initialise();
    
    // 獲取文件名,然後作爲窗口名(沒必要)
    char fn[strlen(path)];
    const char *ptr = strrchr(path, '/');
    sprintf(fn, "%s", ptr+1);
    String title(fn);
    namedWindow(title);
    
    // load 
    FIMULTIBITMAP* fimb = FreeImage_OpenMultiBitmap(FIF_GIF, path,
                                                    0, 1, 0, GIF_PLAYBACK);
    // frame count
    int image_count = FreeImage_GetPageCount(fimb);
    if (!image_count)
        return;
    // pre define size
    int width = 0, height = 0; 
    // other buffer variables
    int mat_type = 0;
    int channels = 0;
    RGBQUAD ptrPalette;
    Mat mat;
    
    for (int cur_frame = 0; cur_frame < image_count; cur_frame++) {
        FIBITMAP* fib_frame = FreeImage_LockPage(fimb, cur_frame);
        
        if (cur_frame == 0) {
            uint min_bits = FreeImage_GetBPP(fib_frame);
            // 現在只適配單個顏色8位,RGB 或 RGBA 的 mat,因此 3*8 或 4*8 位:
            assert(min_bits == 32 || min_bits == 24);
            
            FREE_IMAGE_COLOR_TYPE color_type = FreeImage_GetColorType(fib_frame);
            width = FreeImage_GetWidth(fib_frame);
            height = FreeImage_GetHeight(fib_frame);
            
            if (color_type == FIC_RGBALPHA) {
                mat_type = CV_8UC4;
                channels = 4;
            } else if (color_type == FIC_RGB) {
                mat_type = CV_8UC3;
                channels = 3;
            } else {
                assert(false); // 只適配 RGB 和 RGBA
            }
            mat = Mat(height, width, mat_type);
        }
        
        int base;
        for (int i = 0; i < height; i++) {
            // FreeImage_GetPixel 從左下角開始,因此需要翻轉 y 軸
            uchar* ptrImgDataPerLine = mat.data + (height - i - 1)*mat.step;
            for(int j = 0; j < width; j++) {
                FreeImage_GetPixelColor(fib_frame, j, i, &ptrPalette);
                base = channels*j;
                ptrImgDataPerLine[base] = ptrPalette.rgbBlue;
                ptrImgDataPerLine[base+1] = ptrPalette.rgbGreen;
                ptrImgDataPerLine[base+2] = ptrPalette.rgbRed;
                if (channels == 4)
                    ptrImgDataPerLine[base+3] = ptrPalette.rgbReserved;
            }
        }
        imshow(title, mat);
        FreeImage_UnlockPage(fimb, fib_frame, 1);
        waitKey(interval_ms);
    }
    FreeImage_DeInitialise();
} 

其他

可以稍微修改一下代碼,即可實現獲得 mat 數組或通過回調操作每一幀。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章