0

我对这种东西很陌生。我正在尝试创建一个等效于图像直方图函数的函数。我正在使用 Windows 窗体应用程序来显示直方图(并加载图像)和 CUDA/c++ 来制作直方图。我从一开始就提到我没有使用 openCV、glut、OpenGL 或任何其他第三方库。进行中...我正在尝试将位图传递给非托管 C++ DLL。这里的问题是我现在不知道如何在 c++ 代码中引用该位图。(甚至如何从中获得RGB)。代码片段:

C# :

private void calculateHistogram(object sender, EventArgs e)
{
    Bitmap bmp = (Bitmap)pictureBox1.Image;
    unsafe {
        int** matrixAcumulated;

        var date = bmp.LockBits(new Rectangle(0, 0, pictureBox1.Width, pictureBox1.Height), System.Drawing.Imaging.ImageLockMode.ReadWrite, bmp.PixelFormat);

        matrixAcumulated=NativeMethods.GenerateHistogram(date.Scan0, pictureBox1.Width);

        bmp.UnlockBits(date);

        // Write the string to a file.
        System.Console.WriteLine(matrixAcumulated[0][0]);
    }
}

DLL导入:

using System;
using System.Runtime.InteropServices;

namespace HistogramProcessingCs
{
    class NativeMethods
    {
        [DllImport("HistogramProcessingCpp.dll", CallingConvention = CallingConvention.StdCall)]
        public static extern unsafe int** GenerateHistogram(IntPtr bmp, int dimensionImage);
    }
}

c++:

extern "C" __declspec(dllexport)  int** __stdcall GenerateHistogram(unsigned char *bmp, int dimensionImage)
{
    //How to refere the bitmap from the bmp pointer?
    //dimensionImage is Width = Height
}
4

1 回答 1

1

好的,经过 2 小时的谷歌搜索、stackoverflowing 和 Microsoft 文档记录,我找到了一些东西!

因为您使用的是 CUDA,所以我认为您只想要快速和好的解决方案,这就是为什么我试图找到一种方法,您可以通过 C# 和 C++ 连接来修改数据而无需多次复制数据。

这就是我到目前为止所做的。

有些事情很重要。我使用了一个整数指针,这与当前代码有点混乱。您当然可以改用更有意义的 char 指针(尚未对此进行测试)。另一件事是System.Drawing.Imaging.PixelFormat. 知道您选择了哪个非常重要。在我的示例中,我选择了PixelFormat.Format32bppRgb. 字节顺序(到目前为止我了解到)就是名称的含义。

例子:

32bppRgb代表红色、绿色和蓝色,每个消耗8 位。但是,因为它是这种格式而不是24bppRgb,所以它消耗了一个整数(不使用 8 位)。在这种情况下,没有使用前 8 位(从左到右思考),因此要将像素设置为红色,它的工作原理如下。(抱歉格式化没有按预期工作......)

| 8 | 8 | 8 | 8 | 消耗比特

|空 | 红色 | 绿色 | 蓝色 | 颜色

| 00 | 法郎 | 00 | 00 | 红色的颜色代码

所以红色的代码是 => 0x00 FF 00 00,十进制是 16711680。这就是 C++ 中数字的来源。

C++ 代码:

头文件“NativeLibrary.h”:

namespace NativeLibrary
{
    extern "C" __declspec(dllexport) void __stdcall PassBitmap(int* number, int size);
}

Cpp 文件“NativeLibrary.cpp”:

#include <NativeLibrary.h>

void NativeLibrary::PassBitmap(int* number, int size) {
    for (int i = 0; i < size; i++) {
        number[i] = 16711680;
    }
}

C#代码:

using System.Drawing;
using System.Runtime.InteropServices;

[DllImport("NativeLibrary.dll", CallingConvention = CallingConvention.StdCall)]
public static extern void PassBitmap(IntPtr bmp, int size);

public System.Drawing.Bitmap bitmap = null;


public void GenerateAndModifyBitmap()
{
    //The pixel format is essential!
    System.Drawing.Bitmap bmp = new System.Drawing.Bitmap(100, 100, System.Drawing.Imaging.PixelFormat.Format32bppRgb);

    //Just which region we want to lock of the bitmap
    System.Drawing.Rectangle rect = new System.Drawing.Rectangle(new System.Drawing.Point(), bmp.Size);

    //We want to read and write to the data, pixel format stays the same (anything else wouldn't make much sense)
    System.Drawing.Imaging.BitmapData data = bmp.LockBits(rect, System.Drawing.Imaging.ImageLockMode.ReadWrite, bmp.PixelFormat);

    //This is a pointer to the data in memory. Can be manipulated directly!
    IntPtr ptr = data.Scan0;

    // This code is specific to a bitmap with 32 bits per pixels.
    // Ignore current calculations. They are still work in progress xD
    int size = bmp.Height;
    size *= Math.Abs(data.Stride);
    size /= 4;
    //Call native function with our pointer to the data and of course how many ints we have
    PassBitmap(ptr, size);
    //Work is finished. Give our data back to the manager
    bmp.UnlockBits(data);
    bitmap = bmp;
}

此代码将生成一个完全红色的位图。

于 2017-01-05T21:44:55.480 回答