C# 中的 C++ 内存复制等价物

Posted

技术标签:

【中文标题】C# 中的 C++ 内存复制等价物【英文标题】:C++ Memory Copy Equivalent in C# 【发布时间】:2019-11-01 08:03:11 【问题描述】:

我正在编写一个 Winform 应用程序来从相机中捕获图像。从相机捕获的原始数据需要转换为 DNG 格式。制造商提供了一个描述相同的 C++ 示例。

我在 C# 中使用了相同的逻辑,但是 C# 代码生成的 DNG 图像不正确。

我认为在 C# 代码中,“memcpy_s”等效项没有正确完成,因此它失败了。

由于我对 C++ 的了解不是很透彻,我可能弄乱了 C# 中的逻辑。

任何指针/建议/有价值的指导都会非常有帮助。非常感谢您花时间浏览此代码。

C++ 代码如下。

HRESULT hr = Nncam_PullStillImageV2(m_hcam, NULL, 24, &info);
if (SUCCEEDED(hr))

    void* pRawData = malloc(info.width * info.height);   // allocating memory based on width and Height of the image.
    hr = Nncam_PullStillImage(m_hcam, pRawData, 24, NULL, NULL);
    if (SUCCEEDED(hr))
    
        unsigned nFourCC = 0, bitsperpixel = 0;
        Nncam_get_RawFormat(m_hcam, &nFourCC, &bitsperpixel);

        BITMAPINFOHEADER bmpHeader =  0 ;
        bmpHeader.biSize = sizeof(BITMAPINFOHEADER);
        bmpHeader.biPlanes = 1;
        bmpHeader.biBitCount = bitsperpixel;
        bmpHeader.biWidth = info.width;
        bmpHeader.biHeight = info.height;
        if (bitsperpixel > 8)
        
            bmpHeader.biSizeImage = info.width * info.height * 2;
        
        else
        
            bmpHeader.biSizeImage = info.width * info.height;
        
        bmpHeader.biCompression = nFourCC;

        // core logic for DNG conversion adding headers and rawimage data to Ptr
        void* pDIB = malloc(sizeof(BITMAPINFOHEADER) + bmpHeader.biSizeImage);
        memcpy_s(pDIB, sizeof(BITMAPINFOHEADER), &bmpHeader, sizeof(BITMAPINFOHEADER));
        memcpy_s((char*)pDIB + sizeof(BITMAPINFOHEADER), bmpHeader.biSizeImage,
            pRawData, bmpHeader.biSizeImage);
        XIMAGEINFO imageInfo =  0 ;
        imageInfo.iType = IMAGEFORMAT_DNG;
        imageInfo.iCodec = 1;
        BOOL res = ImageLib_Save(_T("image.dng"), pDIB, &imageInfo);
        free(pDIB);
    
    free(pRawData);

C#代码

 if (cam_.PullStillImageV2(IntPtr.Zero, 24, out info))   /* peek the width and height */
            
                uint pnWidth, pnHeight;
                var sbmp = new Bitmap((int)info.width, (int)info.height, PixelFormat.Format24bppRgb);
                var bmpdata = sbmp.LockBits(new Rectangle(0, 0, sbmp.Width, sbmp.Height), ImageLockMode.WriteOnly, sbmp.PixelFormat);
                if (cam_.PullStillImage(bmpdata.Scan0, 24, out pnWidth, out pnHeight))
                
                    uint nFourCC = 0, bitsperpixel = 0;
                    cam_.get_RawFormat(out nFourCC, out bitsperpixel);
                    BITMAPINFOHEADER bmpHeader = new BITMAPINFOHEADER();
                    bmpHeader.Init();
                    bmpHeader.biPlanes = 1;
                    bmpHeader.biBitCount = bitsperpixel;
                    bmpHeader.biWidth = info.width;
                    bmpHeader.biHeight = info.height;
                    if (bitsperpixel > 8)
                    
                        bmpHeader.biSizeImage = info.width * info.height * 2;
                    
                    else
                    
                        bmpHeader.biSizeImage = info.width * info.height;
                    
                    bmpHeader.biCompression = nFourCC;

        // adding header and rawdata to PDIB might not be correct way as shown in C++
                    IntPtr pDIB = Marshal.AllocHGlobal((int)(Marshal.SizeOf(typeof(BITMAPINFOHEADER)) + bmpHeader.biSizeImage));
                    Marshal.StructureToPtr(bmpHeader, pDIB, true);
                    CopyMemory(pDIB + Marshal.SizeOf(typeof(BITMAPINFOHEADER)), bmpdata.Scan0, bmpHeader.biSizeImage);


                    XIMAGEINFO imageInfo = new XIMAGEINFO();
                    imageInfo.iType = 17;
                    imageInfo.iCodec = 1;
                    ImageLib_Save("image.dng", pDIB, ref imageInfo);
                
            

【问题讨论】:

您正在调用 Windows API 函数 CopyMemory(),它通过 #define CopyMemory RtlCopyMemory 映射到 RtlCopyMemory() - 它本身通过 #define RtlCopyMemory(Destination,Source,Length) memcpy((Destination),(Source),(Length)) 映射到 memcpy()。因此,任何差异都将归因于您正在复制的标题和其他数据,而不是复制本身。 嗨,马特,代码几乎与 C++ 代码相似,不知道有什么区别。 您已经使用了Marshal 类中的几个函数。那里也有一个Marshal.Copy。这不正是您要寻找的吗? 【参考方案1】:

C++ 比 C# 更舒服,我的印象是,在 C++ 中添加标头只是为了在保存后能够将 malloc 的内存识别为图像。

我希望 C# Bitmap 类为您处理。

您是否尝试过简单地保存位图?

【讨论】:

嗨 Fred,Bitmap 不允许我们保存为 DNG,因此所有这些工作都已完成。

以上是关于C# 中的 C++ 内存复制等价物的主要内容,如果未能解决你的问题,请参考以下文章

C# 中的 C++ 模板继承等价物是啥?

java中的C#填充权等价物? [复制]

C++ 等价于 C# 的内部

C++ DWORD 的 C# 等价物是啥?

什么是 C# 的 VB.NET 等价物?操作员? [复制]

什么是 C# 快捷方式测试的 VB .Net 等价物,用于判断事物的真假? [复制]