Ask Your Question

Revision history [back]

click to hide/show revision 1
initial version

Convert DLL IntPtr to byte[] to bitmap

Initially I thought to send an image from C++ opencv to C# required converting the opencv mat to an equivalent emgucv object. I have come to learn that it just requires unpacking the mat object to a type that C# can understand, which is uchar . . .apparently same as byte in C#

I have a C++ program that reads and an image and converts it to uchar (which is what a Mat object is anyway).

void DisplayImage::ReadImage()
{
    cv::Mat image = cv::imread("2015-02-05.jpg");
    image_rows = image.rows;
    image_cols = image.cols;
    image_type  = image.type();
    //image_uchar is data member of uchar*
    image_uchar = MatToBytes(image);
}

uchar *DisplayImage::MatToBytes(cv::Mat image)
{
    int image_size = image.total() * image.elemSize();
    uchar * image_uchar = new uchar[image_size];
    //image_uchar is a class data member of uchar*
    std::memcpy(image_uchar,image.data,image_size * sizeof(uchar));
    return image_uchar;
}

cv::Mat DisplayImage::BytesToMat()
{
    cv::Mat img(image_rows,image_cols,image_type,image_uchar,cv::Mat::AUTO_STEP);
    return img;
}

In the main program I assign a Mat object to the returned value from BytesToMat() and image looks fine.

My DLL looks like below

DisplayImage displayImage = DisplayImage();

extern "C" __declspec(dllexport) void SetImage()
{
    displayImage.ReadImage();   
}

extern "C" __declspec(dllexport) uchar *GetImage()
{
    return displayImage.image_uchar;
}

Just by the way; I firstly started by assigning the pointer to uchar (in C++) with a simple text and displayed it C# by Marshaling returned IntPtr (from dll) to PtrToStringAnsi and it worked.

[DllImport(@".\WrapperForPlayer.dll", CallingConvention = CallingConvention.Cdecl, CharSet = CharSet.Ansi)]
unsafe public static extern IntPtr GetImage();

[DllImport(@".\WrapperForPlayer.dll", CallingConvention = CallingConvention.Cdecl, CharSet = CharSet.Ansi)]
    public static extern void SetImage();

static void Main(string[] args)
{
    //byte[] image_byte  = new byte[500];
    SetImage();
    IntPtr intPtr = GetImage();
    unsafe
    {
        byte* image_byte = (byte*)intPtr;

    }
    Console.Read();
}

The only difference now is that the returned IntPtr contains address to image data which I want to turn to byte[] and then it will be easy to convert to Bitmap. How can I do that?