将OpenCV IplImage或Mat复制到Freeimage FIBITMAP中

时间:2011-02-07 21:51:44

标签: opencv freeimage

我需要在FreeImage(FIBITMAP)和OpenCV格式(IplImage和/或Mat)之间交换数据。我可以将FIBITMAP中的数据转换为IplImage或Mat,因为FreeImage为您提供了FreeImage_GetScanLine函数,您可以将OPenCV imageData ptr设置为等于。

然而,我仍然坚持如何反向,即一旦我有一个OpenCV图像,我如何将其数据转换为FreeImage图像?

3 个答案:

答案 0 :(得分:1)

以下是转换的更详细代码。两个库中都有许多图像数据类型,我尝试支持最常见的图像数据类型。这假设您传递的是cv :: Mat作为源。 FreeImage具有左下角的视角!

/*  These are openCV types
#define CV_8U   0
#define CV_8S   1
#define CV_16U  2
#define CV_16S  3
#define CV_32S  4
#define CV_32F  5
#define CV_64F  6
*/

/*  these are FI types
FIT_UNKNOWN = 0,    // unknown type
FIT_BITMAP  = 1,    // standard image           : 1-, 4-, 8-, 16-, 24-, 32-bit
FIT_UINT16  = 2,    // array of unsigned short  : unsigned 16-bit
FIT_INT16   = 3,    // array of short           : signed 16-bit
FIT_UINT32  = 4,    // array of unsigned long   : unsigned 32-bit
FIT_INT32   = 5,    // array of long            : signed 32-bit
FIT_FLOAT   = 6,    // array of float           : 32-bit IEEE floating point
FIT_DOUBLE  = 7,    // array of double          : 64-bit IEEE floating point
FIT_COMPLEX = 8,    // array of FICOMPLEX       : 2 x 64-bit IEEE floating point
FIT_RGB16   = 9,    // 48-bit RGB image         : 3 x 16-bit
FIT_RGBA16  = 10,   // 64-bit RGBA image        : 4 x 16-bit
FIT_RGBF    = 11,   // 96-bit RGB float image   : 3 x 32-bit IEEE floating point
FIT_RGBAF   = 12    // 128-bit RGBA float image : 4 x 32-bit IEEE floating point

*/

if(_dib)  // get rid of the current dib. 
    FreeImage_Unload(_dib);


int width  = src.size().width;
int height = src.size().height;

switch(src.type())
{
case CV_8U  :{_dib = FreeImage_AllocateT(FIT_BITMAP,width, height, 8) ;}break;  // 8  bit grayscale
case CV_8UC3:{_dib = FreeImage_AllocateT(FIT_BITMAP,width, height, 24);}break;  // 24 bit RGB
case CV_16U :{_dib = FreeImage_AllocateT(FIT_UINT16,width, height, 16);}break;  // 16 bit grayscale
case CV_16S :{_dib = FreeImage_AllocateT(FIT_INT16 ,width, height, 16);}break;
case CV_32S :{_dib = FreeImage_AllocateT(FIT_INT32 ,width, height, 32);}break;
case CV_32F :{_dib = FreeImage_AllocateT(FIT_FLOAT ,width, height, 32);}break;
case CV_64F :{_dib = FreeImage_AllocateT(FIT_DOUBLE,width, height, 32);}break;
default:ASSERT(FALSE);
}

if(_dib==NULL)
    return FALSE;


int srcRowBytes = width  * src.elemSize();

for (int ih=0;ih<height;ih++) 
{
    BYTE* ptr2Line = FreeImage_GetScanLine(_dib,(height-1)-ih);
    memcpy(ptr2Line,src.ptr(ih),srcRowBytes);
}
_bHasChanged = TRUE;

return TRUE;

答案 1 :(得分:0)

好吧,如果你不介意副本,你可以为FIBITMAP创建一个IplImage* / cv::Mat标题,然后复制(使用opencv函数),如下所示:

cv::Mat src; // your source image
FIBITMAP whatever; // allocate space for your FIBITMAP here
cv::Mat wrapper(height, width, CV_8UC3, ptr_from_FIBITMAP, step);
src.copyTo(wrapper);

答案 2 :(得分:0)

你必须要小心谨慎才能复制数据指针,很多图像格式都有填充来启动每个新行,例如4字节边界。

如果你的图像有一个GetScanLine()函数,那么使用从GetScanLine()和cv ::的.ptr()成员返回的指针创建一个空的plImage * / cv :: Mat和memcopy可能更安全。垫

cv::Mat &src        
int srcRowBytes = width  * src.elemSize();

for (int ih=0;ih<height;ih++) {
    memcpy(dest.pointer_to_row(ih),src.ptr(ih),srcRowBytes);
}