因為要用opencv對gif進行處理,查了下,發現有個 FreeImage 的庫 可以用。
FreeImage官網: http://freeimage.sourceforge.net/
下載后,拷貝出 FreeImage.dll FreeImage.lib, FreeImage.h 這是有用的文件。很奇怪這個項目居然沒有文檔說明,只有一些exmaple。
直接貼代碼吧,節省時間。這個例程是可以直接讀取gif的每一幀然后顯示的。
//gif2ipl.cpp
#include <cv.h>
#include <highgui.h>
#include "FreeImage.h"
IplImage* gif2ipl(const char* filename)
{
FreeImage_Initialise(); //load the FreeImage function lib
FREE_IMAGE_FORMAT fif = FIF_GIF;
FIBITMAP* fiBmp = FreeImage_Load(fif,filename,GIF_DEFAULT);
FIMULTIBITMAP * pGIF=FreeImage_OpenMultiBitmap(fif,filename,0,1,0,GIF_PLAYBACK);
// FIBITMAPINFO fiBmpInfo = getfiBmpInfo(fiBmp);
int gifImgCnt=FreeImage_GetPageCount(pGIF);
FIBITMAP * pFrame;
int width,height;
width=FreeImage_GetWidth(fiBmp);
height=FreeImage_GetHeight(fiBmp);
IplImage * iplImg = cvCreateImage(cvSize(width,height),IPL_DEPTH_8U,3);
iplImg->origin = 1;//should set to 1-top-left structure(Windows bitmap style)
RGBQUAD* ptrPalette =new RGBQUAD; // = FreeImage_GetPalette(fiBmp);
BYTE intens;
BYTE* pIntensity = &intens;
cvNamedWindow("gif",0);
printf("gifImgCnt %d \n",gifImgCnt);
for (int curFrame=0;curFrame<gifImgCnt;curFrame++)
{
pFrame= FreeImage_LockPage(pGIF,curFrame);
//ptrPalette = FreeImage_GetPalette(pFrame);
char * ptrImgDataPerLine;
for (int i=0;i<height;i++)
{
ptrImgDataPerLine = iplImg->imageData + i*iplImg->widthStep;
for(int j=0;j<width;j++)
{
//get the pixel index
//FreeImage_GetPixelIndex(pFrame,j,i,pIntensity);
FreeImage_GetPixelColor(pFrame,j,i,ptrPalette);
ptrImgDataPerLine[3*j] = ptrPalette->rgbBlue;
ptrImgDataPerLine[3*j+1] = ptrPalette->rgbGreen;
ptrImgDataPerLine[3*j+2] = ptrPalette->rgbRed;
//ptrImgDataPerLine[3*j] = ptrPalette[intens].rgbBlue;
//ptrImgDataPerLine[3*j+1] = ptrPalette[intens].rgbGreen;
//ptrImgDataPerLine[3*j+2] = ptrPalette[intens].rgbRed;
}
}
printf("convert curFrame end %d \n",curFrame);
cvShowImage("gif",iplImg);
cvWaitKey(30);
FreeImage_UnlockPage(pGIF,pFrame,1);
}
FreeImage_Unload(fiBmp);
FreeImage_DeInitialise();
return iplImg;
}
main.cpp:
#include <opencv2/core/core.hpp>
#include <opencv2/highgui/highgui.hpp>
#include <highgui.h>
#include <cv.h>
#include "opencv2/opencv.hpp"
#include "FreeImage.h"
IplImage* gif2ipl(const char* filename);
int main(int argc,char* argv[])
{
char* filename = (argc == 2)? argv[1] :(char*)"worldCup.gif";
IplImage* iplImg = gif2ipl(filename);
cvReleaseImage(&iplImg);//if used gif2ipl function ,we must use cvReleaseImage to avoid memory leak;
return 0;
}
我用 mingw編譯:makefile:
opencvInclude= -I C:\opencv2.4.4\build\include -I C:\opencv2.4.4\build\include\opencv -I C:\opencv2.4.4\build\include\opencv2
freeimageInclude= -I ../FreeImageLib
cppFlags=-Wall -O2
#cppFlags=-Wall -g
target:main.o gif2ipl.o
g++ $(cppFlags) -o target main.o gif2ipl.o -L E:\Learn\OpenCV\opencv2.4.4\opencv2.4\build\x86\mingw\lib -lopencv_core244 -lopencv_imgproc244 -lopencv_highgui244 -L../FreeImageLib -lFreeImage
main.o:main.cpp
g++ $(cppFlags) $(opencvInclude) $(freeimageInclude) -o main.o -c main.cpp
gif2ipl.o:gif2ipl.cpp
g++ $(cppFlags) $(opencvInclude) $(freeimageInclude) -o gif2ipl.o -c gif2ipl.cpp
.PHONY:clean
clean:
-del *.o target
實際這個轉換感覺要操作每一個像素比較費時間,能否直接讓 IplImage 的 imageData 指向 FreeImage 讀取數據的那片內存了? 對於單通道圖片,我測試時可以的,但是 gif 似乎最高只支持8位256色,所以如果 IplImage是 8位3通道,就不行了,因為數據的內存布局不同。