Search code examples
c++opencvimage-processingc++-cli

C++/CLI Convert Bitmap to OpenCV Mat


I'm trying to develop a small C++/CLI wrapper around OpenCV for use in a C# application. I can't use Emgu since it's for a commercial application.

I'm facing a problem when I'm trying to convert from System.Drawing.Bitmap to OpenCV Mat.

I have the following code:

cv::Mat BitmapToMat(System::Drawing::Bitmap^ bitmap)
{
    System::Drawing::Rectangle blank = System::Drawing::Rectangle(0, 0, bitmap->Width, bitmap->Height);
    System::Drawing::Imaging::BitmapData^ bmpdata = bitmap->LockBits(blank, System::Drawing::Imaging::ImageLockMode::ReadWrite, System::Drawing::Imaging::PixelFormat::Format24bppRgb);
    cv::Mat cv_img(cv::Size(bitmap->Width, bitmap->Height), CV_8UC3, bmpdata->Scan0.ToPointer(), cv::Mat::AUTO_STEP);
    bitmap->UnlockBits(bmpdata);

    return cv_img;
}

I'm using it in cpp file to test out the generated Mat like this:

Mat image = BitmapToMat(templateImage);
cv::imwrite("some2.jpg", image);

But the image produced is completely distorted (see images)

INPUT BITMAP IMAGE

ORIGINAL IMAGE

RESULT MAT IMAGE SAVED TO FILE

RESULT IMAGE


Solution

  • Windows bitmaps are padded. You want to calculate "width in bytes" of the bitmap row, and supply that instead of cv::Mat::AUTO_STEP:

    int wb = ((bitmap->Width * 24 + 31) / 32) * 4;
    cv::Mat cv_img(cv::Size(bitmap->Width, bitmap->Height), 
        CV_8UC3, bmpdata->Scan0.ToPointer(), wb);