C#Bitmap GetPixel(),GPU中的SetPixel()

时间:2017-02-04 07:21:32

标签: c# image bitmap gpgpu cudafy.net

我使用Cudafy作为c#包装器 我需要获取位图的颜色信息InputBitmap0.GetPixel(x, y)并为输出创建一个新的位图。

我需要在GPU中完成以下工作。

IN CPU

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

简而言之:

如何为输入Bitmap的每个像素点设置GetPixel(),为GPU中的outputbitmap Bitmap的每个像素点设置SetPixel()。

2 个答案:

答案 0 :(得分:5)

  

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

需要时间,但最后,我破了我的案子。

我们有两个Bitmap:一个用于输出OutputBitmap,另一个用于输入InputBitmap0

让我们将此任务分成几部分:

  1. InputBitmap0.GetPixel()x坐标
  2. 执行y
  3. 然后,OutputBitmap.SetPixel()使用不同的坐标object_point_x, object_point_y
  4. Cudafy不支持BitmapColor类型数据。所以我将位图转换为byte类型。

    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.
    

    我们已将InputBitmap0的内容复制到rgbValues数组。现在我们需要做GetPixel()的工作(得到R,G,B,A的值)。

    我们还需要为OutputBitmap执行上述工作(make array),因为我们将在GPU中执行SetPixel()但我们稍后会将数据复制回位图。

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

    它的GPU计算时间。让我们初始化gpu。

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

    现在将input_ragba_coloroutput_ragba发送到gpu,因为我们可以迭代数组并进行任何计算。

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

    现在在GPU(内核)内部

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

    我正在考虑解决第一项任务的每个R,G,B,A,ex:input_ragba_color[(y * stride0) + (x * 4) + 1]的值   (InputBitmap0.GetPixel()

         

    dev_output_rgba_colorinput_ragba_color的值   例如:

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

    这解决了我们的第二项任务(OutputBitmap.SetPixel()

    我们现在知道gpu为我们的dev_output_rgba_color填充了一个数组(OutputBitmap)。

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

    使用内存指针将结果复制回OutputBitmap并将其从内存中解锁。

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

    现在OutputBitmap包含更新的值。

答案 1 :(得分:1)

我认为你需要使用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; } 并在GPU上分配它。 I've seen you asking around这个答案正在进行中,我会在接下来的几天里不断更新,因为我有时间。

{{1}}