如果要将新版本的OpenCVcv::Mat显示到HWND上,之前都是说使用修改过的CvvImage类进行显示,但是这个类有个缺点就是不能显示带有透明通道的cv::Mat,而目前好的方式是将cv::Mat转换为MFC的CImage类,不过之前别人写的都只是支持CV_8UC1CV_8UC3cv::Mat对象,也不支持四通道的转换,我在本文中对这个功能进行了扩展,支持CV_8UC4cv::Mat转换为CImage类,这样就支持在HWND上显示透明的cv::Mat图片了。

1 cv::Mat转换为CImage

下面就是我改写的代码,扩展了带有透明通道的cv::Mat转换为CImage

bool RenderCvMatToHWnd::ConvertMat2CImage(const cv::Mat& src_img, CImage& dst_img)
{
    if (src_img.empty())
    {
        return false;
    }

    int width = src_img.cols;           //获取输入图像的宽度  
    int height = src_img.rows;          //获取输入图像的高度  
    int channels = src_img.channels();  //获取输入图像的通道数  
    int type = src_img.type();

    dst_img.Destroy();

    switch (type)
    {
    case CV_8UC1:
    {
        dst_img.Create(width, -1 * height, 8 * channels);
        unsigned char* dst_data = static_cast<unsigned char*>(dst_img.GetBits());
        int step_size = dst_img.GetPitch();     //获取位图行与行之间相差的字节数  
        unsigned char* src_data = nullptr;
        for (int i = 0; i < height; i++)
        {
            src_data = const_cast<unsigned char*>(src_img.ptr<unsigned char>(i));   //获取行指针  
            for (int j = 0; j < width; j++)
            {
                if (step_size > 0)
                {
                    *(dst_data + step_size * i + j) = *src_data++;
                }   //像素的排列方式是自左上开始的  
                else
                {
                    *(dst_data + step_size * i - j) = *src_data++;
                }
            }
        }
        break;
    }
    case CV_8UC3:
    {
        dst_img.Create(width, height, 8 * channels);
        unsigned char* dst_data = static_cast<unsigned char*>(dst_img.GetBits());
        int step_size = dst_img.GetPitch();     //获取位图行与行之间相差的字节数  
        unsigned char* src_data = nullptr;
        for (int i = 0; i < height; i++)
        {
            src_data = const_cast<unsigned char*>(src_img.ptr<unsigned char>(i));   //获取行指针  
            for (int j = 0; j < width; j++)
            {
                for (int k = 0; k < 3; k++)
                {
                    *(dst_data + step_size * i + j * 3 + k) = src_data[3 * j + k];
                }
            }
        }
        break;
    }
    case CV_8UC4:
    {
        dst_img.Create(width, height, 8 * channels);
        unsigned char* dst_data = static_cast<unsigned char*>(dst_img.GetBits());
        int step_size = dst_img.GetPitch();     //获取位图行与行之间相差的字节数  
        unsigned char* src_data = nullptr;
        for (int i = 0; i < height; i++)
        {
            src_data = const_cast<unsigned char*>(src_img.ptr<unsigned char>(i));   //获取行指针  
            for (int j = 0; j < width; j++)
            {
                for (int k = 0; k < 4; k++)
                {
                    *(dst_data + step_size * i + j * 4 + k) = src_data[4 * j + k];
                }
            }
        }
        break;
    }
    default:
        break;
    }

    return true;
}

参考