2017-01-05 36 views
0

Я новичок в этом. Я пытаюсь создать функцию, которая эквивалентна функции гистограммы изображения. Я использую приложение форм Windows для отображения гистограммы (и загрузки изображения) и CUDA/C++ для создания гистограммы. Я с самого начала упоминаю, что я НЕ использую openCV, glut, OpenGL или любую другую третью библиотеку. Выполнение ... Я пытаюсь передать растровое изображение в неуправляемую библиотеку C++. Проблема здесь в том, что я не сейчас, как ссылаться на это растровое изображение в коде C++. (И даже, как получить RGB из него). Отрывки кода:Загрузить изображение из указателя в CUDA с экспортом dll

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 
} 
+0

Я копаю в этом –

+0

Надеюсь, мой ответ поможет людям! :)! Спасибо за этот вопрос. Теперь я знаю, как делать C++ с помощью C#: D –

ответ

1

Хорошо, я разработал что-то после 2-х часов прибегая к помощи, stackoverflowing и Microsoft документации!

Поскольку вы используете CUDA, я думаю, что вам нужны только быстрые и приятные решения, поэтому я попытался найти способ, с помощью которого вы можете изменять данные, не копируя их много раз только из-за C# и C++-соединения.

Это то, что я сделал до сих пор.

Некоторые вещи важны. Я использовал целочисленный указатель, это немного грязно с текущим кодом. Вы можете, конечно, использовать вместо этого указатель char, который имеет гораздо больше смысла (не проверял это). Другое дело, что System.Drawing.Imaging.PixelFormat. Очень важно знать, что вы выбрали. В моем примере я выбрал PixelFormat.Format32bppRgb. Порядок байтов (до сих пор я узнал), как это называется.

Пример:

32bppRgb обозначает красного, зеленого и синего которые потребляют каждый 8 битов. Однако, поскольку это такой формат, а не 24bppRgb, он потребляет целое число (8 бит не используются). В этом случае используются первые 8 бит arent (слева направо), поэтому для установки пикселя в красный цвет он работает следующим образом. (Извините, форматирование не сработало, как ожидалось ...)

| 8 | 8 | 8 | 8 | потребляющие биты

| пусто | красный | зеленый | синий | цвет

| 00 | FF | 00 | 00 | Цветовой код для красного

Поэтому код для красного это => 0x00 FF 00 00 и, как десятичное это 16711680. Вот где число в C++ приходит.

C++ Код:

Заголовочный файл «NativeLibrary.ч ":

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; 
} 

Этот код будет генерировать растровое изображение, которое полностью красным.

+0

Спасибо большое! Ты сделал это!! –

+0

Ха-ха большое спасибо: D. Если в этом вопросе ничего не осталось, не стесняйтесь комментировать. Я просто думаю о улучшениях –