10

I am using Cudafy as c# wrapper I need to get colour info InputBitmap0.GetPixel(x, y) of a bitmap and make an new bitmap for output .

I need the following work to be done in GPU.

IN CPU

OutputBitmap.SetPixel(object_point_x, object_point_y, InputBitmap0.GetPixel(x, y));

In short:

How to GetPixel() for each pixel point of the input Bitmap, SetPixel() for each pixel point of the outputbitmap Bitmap in GPU.

Md Sifatul Islam
  • 846
  • 10
  • 28
  • this question is way too broad as written and I have voted to close it as such – talonmies Feb 04 '17 at 11:17
  • @talonmies I have tried to be detailed so that contributors can understand it easily! Instead of closing it down can I get to learn one possible way of solving it? – Md Sifatul Islam Feb 04 '17 at 11:28
  • You haven't asked a serious question here. What *exactly* do you what to know? CUDA doesn't have native C# bindings and you have not even said what framework you are using. Do you understand the bit map data format? Have you tried actually writing a kernel? What is the problem if you have? That is why this is too broad. You have posted a wish list, not a [SO] question – talonmies Feb 04 '17 at 12:00
  • @talonmies thnx for your response! I have narrowed down my question! Can you please help now? – Md Sifatul Islam Feb 04 '17 at 14:45
  • I believe CUDAfy.NET targers mostly non-graphics related intensive numeric operations, while you're looking at graphics operations, served by CUDA's NPP https://developer.nvidia.com/npp (which doesn't seem to be supported by CUDAfy.NET) – Simon Mourier Mar 05 '17 at 08:46
  • @Md.Sifatul Islam, you can try to play with pixel shader in MonoGame. – SeNS Mar 08 '17 at 14:29
  • @SeNS thnx buddy solved my problem! – Md Sifatul Islam Mar 10 '17 at 19:32
  • @Md.Sifatul Islam, should I post an answer to get bounty points? Could you provide code snippet for this? – SeNS Mar 11 '17 at 23:28

2 Answers2

5

OutputBitmap.SetPixel(object_point_x, object_point_y, InputBitmap0.GetPixel(x, y))

It took time but finally, I , cracked my case.

We have two Bitmap : one for output OutputBitmap and another for input InputBitmap0

Lets divide this task into parts:

  1. do InputBitmap0.GetPixel() for x ,y coordinate
  2. then , OutputBitmap.SetPixel() for a different coordinate object_point_x, object_point_y

Cudafy does not support Bitmap or Color type data. So I converted the Bitmaps to byte type.

BitmapData InputBitmapData0 = InputBitmap0.LockBits(new Rectangle(0, 0, InputBitmap0.Width, InputBitmap0.Height), ImageLockMode.ReadOnly, PixelFormat.Format32bppArgb);

IntPtr ptr0 = InputBitmapData0.Scan0;//pointer for color

int stride0 = InputBitmapData0.Stride;

byte[]  input_ragba_color = new byte[InputBitmapData0.Stride * InputBitmap0.Height];

Marshal.Copy(ptr0, input_ragba_color, 0, bytes0);// Copy the RGB values of color value into the array.

We have copied the content of the InputBitmap0 to the rgbValues array. Now we need to do the work of GetPixel() (get the values of R,G,B,A).

We need to do the above work ( make array) for OutputBitmap too because we will be doing SetPixel() in GPU but we will copy the array back to the bitmap later.

BitmapData OutputBitmapData = OutputBitmap.LockBits(new Rectangle(0, 0, OutputBitmap.Width, OutputBitmap.Height), ImageLockMode.WriteOnly, OutputBitmap.PixelFormat);
IntPtr ptr_output = OutputBitmapData.Scan0;

byte[] output_ragba = new byte[OutputBitmapData.Stride * OutputBitmap.Height]; 

Its GPU time for calculation. Lets initialize gpu.

CudafyModule km = new CudafyTranslator.Cudafy();
GPGPU gpu = new CudafyHost.getDevice(CudafyModes.Target, CudafyModes.DeviceId);
gpu.LoadModule(km);

Now send input_ragba_color and output_ragba to the gpu because we can iterate the array and do any calculation.

byte[] dev_output_rgba_color = gpu.Allocate<byte>(output_ragba.Length);
byte[] dev_input_ragba_color = gpu.CopyToDevice(input_ragba_color);
gpu.Launch(N, 1).update_bitmap(x, y, object_point_x, object_point_y,int stride0, int OutputBitmapData.Stride,dev_input_ragba_color,dev_output_rgba_color);

Now inside GPU(kernel)

[Cudafy]
public static void update_bitmap(GThread thread, int x,int y,int object_point_x,int  object_point_y,int stride0, int OutputBitmapData_Stride,byte [] dev_input_ragba_color,byte [] dev_output_rgba_color)
{
   dev_output_rgba_color[(object_point_y * OutputBitmapData_Stride) + (object_point_x * 4)] = input_ragba_color[(y * stride0) + (x * 4)];  
   dev_output_rgba_color[(object_point_y * OutputBitmapData_Stride) + (object_point_x * 4) + 1] = input_ragba_color[(y * stride0) + (x * 4) + 1];
   dev_output_rgba_color[(object_point_y * OutputBitmapData_Stride) + (object_point_x * 4) + 2] = input_ragba_color[(y * stride0) + (x * 4) + 2];
   dev_output_rgba_color[(object_point_y * OutputBitmapData_Stride) + (object_point_x * 4) + 3] = input_ragba_color[(y * stride0) + (x * 4) + 3];

}

I am taking values of each R,G,B,A ,ex: input_ragba_color[(y * stride0) + (x * 4) + 1] which is solving 1st task (InputBitmap0.GetPixel())

dev_output_rgba_color is taking the values of input_ragba_color example:

dev_output_rgba_color[(object_point_y * OutputBitmapData_Stride) + (object_point_x * 4)] = input_ragba_color[(y * stride0) + (x * 4)]; 

which is solves our 2nd task (OutputBitmap.SetPixel())

We now know that gpu has populated an array(dev_output_rgba_color) for our OutputBitmap.

gpu.CopyFromDevice(dev_output_rgba_color, output_ragba);   //dev_output_rgba_color values will be assigned to output_ragba
gpu.FreeAll();

Copy the result back to the OutputBitmap using the memory pointer and unlock it from the memory.

Marshal.Copy(output_ragba, 0, ptr_output, output_bytes);// Copy the RGB values of color value into the array.
OutputBitmap.UnlockBits(OutputBitmapData);

Now the OutputBitmap contains the updated values.

Md Sifatul Islam
  • 846
  • 10
  • 28
1

I think you will need to use a byte[] and allocate that on the GPU. I've seen you asking around and this answer is a work in progress, I'll keep updating it over the next few days as I get time.

CudafyModule km = new CudafyTranslator.Cudafy();
GPGPU gpu = new CudafyHost.getDevice(CudafyModes.Target, CudafyModes.DeviceId);
gpu.LoadModule(km);

var image = new Bitmap(width, height);
image = (Bitmap)Image.FromFile(@"C:\temp\a.bmp", true);
byte[] imageBytes = new byte[width * height * 4];
using(MemoryStream ms = new MemoryStream())
{
    image.Save(ms, format);
    imageBytes = ms.ToArray();
}
byte[] device_imageBytes = _gpu.CopyToDevice(imageBytes);

byte r = 0;
byte g = 0;
byte b = 0;

byte device_r = _gpu.Allocate<byte>(r);
byte device_g = _gpu.Allocate<byte>(g);
byte device_b = _gpu.Allocate<byte>(b);

//Call this in a loop
gpu.Launch(N, 1).GetPixel(x, y, device_imageBytes, device_r, device_g, device_b);

...

[Cudafy]
public static void GetPixel(GThread thread, int x, int y, byte[] imageBytes, byte blue, byte green, byte red)
{
    int offset = x * BPP + y * stride;
    blue = imageBytes[offset++];
    green = imageBytes[offset++];
    red = imageBytes[offset];

    double R = red;
    double G = green * 255;
    double B = blue * 255 * 255;

}
Jeremy Thompson
  • 61,933
  • 36
  • 195
  • 321