封装类声明(CImageMat.h):
// CImageMat.h
class CImageMat
{
public:
/*MatToCImage
*简介:
* OpenCV的Mat转ATL/MFC的CImage,仅支持单通道灰度或三通道彩色
*参数:
* mat:OpenCV的Mat
* cimage:ATL/MFC的CImage
*/
static void MatToCImage(Mat& mat, CImage& cimage);
/*CImageToMat
*简介:
* ATL/MFC的CImage转OpenCV的Mat,仅支持单通道灰度或三通道彩色
*参数:
* cimage:ATL/MFC的CImage
* mat:OpenCV的Mat
*/
static void CImageToMat(CImage& cimage, Mat& mat);
static void CGdiImageToMat(Gdiplus::Bitmap* image, Mat& mat);
static Gdiplus::Bitmap* MatToCGdiImage(Mat& mat);
static void BitmapToIplImage(Gdiplus::Bitmap* pBitmap, IplImage* &pIplImg);
static void IplImageToBitmap(IplImage* pIplImg, Gdiplus::Bitmap* &pBitmap);
};
源码实现(CImageMat.cpp):
#include "stdafx.h"
#include "ImageMat.h"
void CrossImage(CImage &img) //对像素进行转换
{
for (int i = 0; i < img.GetWidth(); i++)
{
for (int j = 0; j < img.GetHeight(); j++)
{
UCHAR *cr = (UCHAR*)img.GetPixelAddress(i, j);
cr[0] = cr[0] * cr[3] / 255;
cr[1] = cr[1] * cr[3] / 255;
cr[2] = cr[2] * cr[3] / 255;
}
}
}
void CImageMat::MatToCImage(Mat& mat, CImage& cimage)
{
if (0 == mat.total())
return;
int nChannels = mat.channels();
if ((1 != nChannels) && (3 != nChannels))
return;
int nWidth = mat.cols;
int nHeight = mat.rows;
//重建cimage
cimage.Destroy();
cimage.Create(nWidth, nHeight, 8 * nChannels);
//拷贝数据
uchar* pucRow; //指向数据区的行指针
uchar* pucImage = (uchar*)cimage.GetBits(); //指向数据区的指针
int nStep = cimage.GetPitch(); //每行的字节数,注意这个返回值有正有负
if (1 == nChannels) //对于单通道的图像需要初始化调色板
{
RGBQUAD* rgbquadColorTable;
int nMaxColors = 256;
rgbquadColorTable = new RGBQUAD[nMaxColors];
cimage.GetColorTable(0, nMaxColors, rgbquadColorTable);
for (int nColor = 0; nColor < nMaxColors; nColor++)
{
rgbquadColorTable[nColor].rgbBlue = (uchar)nColor;
rgbquadColorTable[nColor].rgbGreen = (uchar)nColor;
rgbquadColorTable[nColor].rgbRed = (uchar)nColor;
}
cimage.SetColorTable(0, nMaxColors, rgbquadColorTable);
delete[]rgbquadColorTable;
}
for (int nRow = 0; nRow < nHeight; nRow++)
{
pucRow = (mat.ptr<uchar>(nRow));
for (int nCol = 0; nCol < nWidth; nCol++)
{
if (1 == nChannels)
{
*(pucImage + nRow * nStep + nCol) = pucRow[nCol];
}
else if (3 == nChannels)
{
for (int nCha = 0; nCha < 3; nCha++)
{
*(pucImage + nRow * nStep + nCol * 3 + nCha) = pucRow[nCol * 3 + nCha];
}
}
}
}
}
void CImageMat::CImageToMat(CImage& cimage, Mat& mat)
{
if (true == cimage.IsNull())
{
return;
}
int nChannels = cimage.GetBPP() / 8;
if ((1 != nChannels) && (3 != nChannels))
{
return;
}
int nWidth = cimage.GetWidth();
int nHeight = cimage.GetHeight();
//重建mat
if (1 == nChannels)
{
mat.create(nHeight, nWidth, CV_8UC1);
}
else if (3 == nChannels)
{
mat.create(nHeight, nWidth, CV_8UC3);
}
else if (4 == nChannels)
{
mat.create(nHeight, nWidth, CV_8UC4);
}
//拷贝数据
uchar* pucRow; //指向数据区的行指针
uchar* pucImage = (uchar*)cimage.GetBits(); //指向数据区的指针
int nStep = cimage.GetPitch(); //每行的字节数,注意这个返回值有正有负
for (int nRow = 0; nRow < nHeight; nRow++)
{
pucRow = (mat.ptr<uchar>(nRow));
for (int nCol = 0; nCol < nWidth; nCol++)
{
if (1 == nChannels)
{
pucRow[nCol] = *(pucImage + nRow * nStep + nCol);
}
else if (3 == nChannels || 4 == nChannels)
{
for (int nCha = 0; nCha < nChannels; nCha++)
{
pucRow[nCol * 3 + nCha] = *(pucImage + nRow * nStep + nCol * nChannels + nCha);
}
}
}
}
}
void CImageMat::CGdiImageToMat(Gdiplus::Bitmap *image, Mat& mat)
{
Gdiplus::BitmapData source;
Gdiplus::Rect rect(0, 0, image->GetWidth(), image->GetHeight());
Gdiplus::Status status = image->LockBits(&rect, Gdiplus::ImageLockModeRead, image->GetPixelFormat(), &source);
if (status != Gdiplus::Ok) {
return ;
}
int nWidth = image->GetWidth();
int nHeight = image->GetHeight();
if (Gdiplus::IsAlphaPixelFormat((Gdiplus::PixelFormat)image->GetPixelFormat()))
mat.create(nHeight, nWidth, CV_8UC4);
else
mat.create(nHeight, nWidth, CV_8UC3);
BYTE *destination = (BYTE *)mat.data;
for (int y = 0; y != source.Height; ++y) {
BYTE *src = (BYTE *)source.Scan0 + y * source.Stride;
BYTE *dst = (BYTE *)(destination + y * mat.step);
memcpy(dst, src, mat.channels() * source.Width);
}
image->UnlockBits(&source);
}
Gdiplus::Bitmap* CImageMat::MatToCGdiImage(Mat& mat)
{
cv::cuda::GpuMat matg;
if (mat.empty())
return NULL;
//检查图像位深
if (mat.depth() != CV_8U)
{
return NULL;
}
//cv::Mat newMat;
if (mat.channels() == 1)
cv::cvtColor(mat, mat, CV_GRAY2BGRA);
else if (mat.channels() == 3)
cv::cvtColor(mat, mat, CV_BGR2BGRA);
else
mat = mat;
//Gdiplus::Bitmap src(newMat.cols, newMat.rows, newMat.step1(), PixelFormat32bppARGB, newMat.data);
//return src.Clone(0, 0, src.GetWidth(), src.GetHeight(), PixelFormat32bppARGB);
//Gdiplus::Bitmap* image = src.Clone(0, 0, src.GetWidth(), src.GetHeight(), PixelFormat32bppARGB);
Gdiplus::Bitmap* image = new Gdiplus::Bitmap(mat.cols, mat.rows, mat.step1(), PixelFormat32bppARGB, mat.data);
return image;
}
void CImageMat::BitmapToIplImage(Gdiplus::Bitmap* pBitmap, IplImage* &pIplImg)
{
if (!pBitmap)
return;
if (pIplImg)
{
cvReleaseImage(&pIplImg);
pIplImg = NULL;
}
BitmapData bmpData;
Gdiplus::Rect rect(0, 0, pBitmap->GetWidth(), pBitmap->GetHeight());
pBitmap->LockBits(&rect, ImageLockModeRead, PixelFormat24bppRGB, &bmpData);
IplImage* tempImg = cvCreateImage(cvSize(pBitmap->GetWidth(), pBitmap->GetHeight()), IPL_DEPTH_8U, 3);
BYTE* temp = (bmpData.Stride > 0) ? ((BYTE*)bmpData.Scan0) : ((BYTE*)bmpData.Scan0 + bmpData.Stride*(bmpData.Height - 1));
memcpy(tempImg->imageData, temp, abs(bmpData.Stride)*bmpData.Height);
pBitmap->UnlockBits(&bmpData);
pIplImg = tempImg;
//判断Top-Down or Bottom-Up
if (bmpData.Stride < 0)
cvFlip(pIplImg, pIplImg);
}
void CImageMat::IplImageToBitmap(IplImage* pIplImg, Gdiplus::Bitmap* &pBitmap)
{
if (!pIplImg)
return;
BITMAPINFOHEADER bmih;
memset(&bmih, 0, sizeof(BITMAPINFOHEADER));
bmih.biSize = sizeof(BITMAPINFOHEADER);
bmih.biWidth = pIplImg->width;
bmih.biHeight = pIplImg->height;
bmih.biPlanes = 1;
bmih.biBitCount = pIplImg->depth*pIplImg->nChannels;
bmih.biSizeImage = pIplImg->imageSize;
BYTE* pData = new BYTE[bmih.biSizeImage];
memcpy(pData, pIplImg->imageDataOrigin, pIplImg->imageSize);
if (pBitmap)
{
delete pBitmap;
pBitmap = NULL;
}
pBitmap = Gdiplus::Bitmap::FromBITMAPINFO((BITMAPINFO*)&bmih, pData);
}