OpenCVでGIFの読み書きできないのでimgctl.dllというグラフィックライブラリを使ってみた。
→ imgctl.dll
OpenCVと組み合わせて、GIFの読み書きだけimgctl.dllを使って、あとの画像処理はOpenCVで行うという使い方をしようとしている。
他にもgiflibとかlibGDとかのグラフィックライブラリを試してみたのだけど、自分にはimgctl.dllが一番使いやすくて理解しやすかった。
まず、GIFファイルを読み込むのを作ってみた。
コードは以下のように書いた。
main関数ではload_GIF()を呼び出してGIFファイルを読み込んで、OpenCVのcvSaveImage()でJPEGで書き出すというサンプルコードになっている。
#include <windows.h> #include <stdio.h> #include <stdlib.h> #include "imgctl.h" #include "opencv2/opencv.hpp" IplImage *load_GIF(char *filename) { HDIB hDib=NULL; BITMAPINFOHEADER bih; unsigned char *bitmapData; DWORD ret; DWORD dwDataSize = 0; IplImage *image; int wd,ht; int i,j; // load GIF ImgctlErrorClear(); hDib = GIFtoDIB(filename); ret = ImgctlError(); if ( ret!=ICERR_NONE ) { return NULL; // Error: File not found. } // to 24bit DIBto24Bit(hDib); // get bitmap data HeadDIB(hDib, &bih); GetDIB(hDib, NULL, NULL, NULL, &dwDataSize); bitmapData = (unsigned char *)malloc(dwDataSize); if (bitmapData==NULL) { return NULL; } GetDIB(hDib, NULL, NULL, bitmapData, &dwDataSize); // IPL image wd=bih.biWidth; ht=bih.biHeight; image = cvCreateImage(cvSize(wd,ht),IPL_DEPTH_8U,3); // copy bitmap data for (i=0;i<ht;i++) { for (j=0;j<wd;j++) { image->imageData[image->widthStep*i+j*3 ] = bitmapData[ (j+(ht-i-1)*wd)*3 ]; image->imageData[image->widthStep*i+j*3+1] = bitmapData[ (j+(ht-i-1)*wd)*3+1]; image->imageData[image->widthStep*i+j*3+2] = bitmapData[ (j+(ht-i-1)*wd)*3+2]; } } free(bitmapData); DeleteDIB(hDib); return image; } int main() { IplImage *image1; // load GIF image1 = load_GIF("test.GIF"); if (image1==NULL) { printf("Error\n"); return 1; } // output to JPEG cvSaveImage("output.jpg",image1); return 0; }
次に、GIFの書き出しも作ってみた。
上記のサンプルコードの逆で、cvLoadImage()でJPEGファイルを読み込んで、save_GIF()でGIFファイルを書き出すというサンプルコードになっている。
#include <windows.h> #include <stdio.h> #include <stdlib.h> #include "imgctl.h" #include "opencv2/opencv.hpp" int save_GIF(char *filename,IplImage *image) { HDIB hDib = NULL; BITMAPINFO bmpInfo; unsigned char *bitmapData; DWORD ret; int wd,ht; int i,j; wd = image->width; ht = image->height; bitmapData = (unsigned char *)malloc(wd*ht*3); if (bitmapData==NULL) { return 1; // error } ZeroMemory(&bmpInfo, sizeof(bmpInfo)); bmpInfo.bmiHeader.biSize = sizeof(BITMAPINFOHEADER); bmpInfo.bmiHeader.biWidth = wd; bmpInfo.bmiHeader.biHeight = ht; bmpInfo.bmiHeader.biPlanes = 1; bmpInfo.bmiHeader.biBitCount = 24; bmpInfo.bmiHeader.biCompression = BI_RGB; for (i=0;i<ht;i++) { for (j=0;j<wd;j++) { bitmapData[ (j+(ht-i-1)*wd)*3 ] = image->imageData[image->widthStep*i+j*3]; bitmapData[ (j+(ht-i-1)*wd)*3+1] = image->imageData[image->widthStep*i+j*3+1]; bitmapData[ (j+(ht-i-1)*wd)*3+2] = image->imageData[image->widthStep*i+j*3+2]; } } // create HDIB data hDib = CreateDIB(&bmpInfo,bitmapData); // GIF output ret = DIBtoGIF(filename,hDib,FALSE); if (!ret) { DeleteDIB(hDib); return 1; // Error: output failed } free(bitmapData); DeleteDIB(hDib); return 0; } int main() { IplImage *image1; int ret; // load JPEG image1 = cvLoadImage("test.jpg", CV_LOAD_IMAGE_COLOR); // output to GIF ret = save_GIF("output.gif",image1); if (ret!=0) { printf("Error\n"); return 1; } return 0; }
とりあえず作ったけど、GIF形式はもう時代遅れなので使うニーズはほとんど無いと思う。
でもこれで大体、imgctl.dllの使い方をマスターできたようだ。
アニメーションGIFについてはまだしばらくは使われそうな感じだし、自分でもちょっと作ってみたいソフトがあるので、imgctl.dllのアニメーションGIFの書き出しとかを使って何か作ってみる予定だ。