Reputation: 1447
I am new to this kind of stuff. I'm trying to create a function which is equivalent to the histogram function of an image. I am using windows forms application to show the histogram (and load the image) and CUDA/c++ to make the histogram. I am mentioning from the beginning that I am NOT using openCV, glut, OpenGL or any other third library. Carrying on... I am trying to pass a bitmap to an unmanaged c++ DLL. The problem here is that I don't now how to reference that bitmap in the c++ code. (And even how to get the RGB out of it). Snippets of code:
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 import :
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
}
Upvotes: 0
Views: 442
Reputation: 634
Okay I worked out something after 2 hours of googling, stackoverflowing and microsoft documentationing!
Because you're using CUDA I think you only want fast and nice solutions, that's why I tried to find a way with which you can modify data without copying it many times only because of C# and C++ connection.
That's what I've done so far.
Some things are important.
I used an integer pointer, that's a bit messy with the current code.
You can of course use instead a char pointer which makes much more sense (haven't tested this).
Another thing is the System.Drawing.Imaging.PixelFormat
.
It's really important to know which you have choosen. In my example I've choosen PixelFormat.Format32bppRgb
.
The byte order is (so far I learned) just how the name is.
32bppRgb stands for red, green and blue which consume each 8 bits. However because it's this format and not 24bppRgb it consumes a whole integer(8 bits aren't used). In this case the first 8 bits arent used (left to right thinking) so to set a pixel to red it works like this. (Sorry formating didn't worked as expected...)
| 8 | 8 | 8 | 8 | consuming bits
|empty | red | green | blue | color
| 00 | FF | 00 | 00 | color code for red
So the code for red is this => 0x00 FF 00 00 and as decimal it's 16711680. That's where the number in the C++ comes from.
Header file "NativeLibrary.h":
namespace NativeLibrary
{
extern "C" __declspec(dllexport) void __stdcall PassBitmap(int* number, int size);
}
Cpp file "NativeLibrary.cpp":
#include <NativeLibrary.h>
void NativeLibrary::PassBitmap(int* number, int size) {
for (int i = 0; i < size; i++) {
number[i] = 16711680;
}
}
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;
}
This code would generate a bitmap which is completely red.
Upvotes: 2