GPU 中的 C# 位图 GetPixel()、SetPixel()
C# Bitmap GetPixel(), SetPixel() in GPU
我正在使用 Cudafy 作为 C# 包装器
我需要获取位图的颜色信息 InputBitmap0.GetPixel(x, y)
并为输出制作新的位图。
我需要在 GPU 中完成以下工作。
IN CPU
OutputBitmap.SetPixel(object_point_x, object_point_y, InputBitmap0.GetPixel(x, y));
简而言之:
如何在 GPU 中为输入位图的每个像素点获取 GetPixel(),为输出位图位图的每个像素点设置像素点。
我认为您需要使用 byte[]
并将其分配到 GPU 上。 I've seen you asking around 这个答案还在制作中,我会在接下来几天有空时不断更新它。
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;
}
OutputBitmap.SetPixel(object_point_x, object_point_y, InputBitmap0.GetPixel(x, y))
这花了一些时间,但我终于破案了。
我们有两个 Bitmap
:一个用于输出 OutputBitmap
,另一个用于输入 InputBitmap0
让我们把这个任务分成几个部分:
- 为
x
做InputBitmap0.GetPixel()
,y
坐标
- 然后 ,
OutputBitmap.SetPixel()
换一个坐标 object_point_x, object_point_y
Cudafy 不支持 Bitmap
或 Color
类型的数据。所以我将位图转换为 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
做上述工作(制作数组),因为我们将在 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_color
和 output_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];
}
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()
)
我们现在知道 gpu 已经为我们的 OutputBitmap
填充了一个数组 (dev_output_rgba_color
)。
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
包含更新后的值。
我正在使用 Cudafy 作为 C# 包装器
我需要获取位图的颜色信息 InputBitmap0.GetPixel(x, y)
并为输出制作新的位图。
我需要在 GPU 中完成以下工作。
IN CPU
OutputBitmap.SetPixel(object_point_x, object_point_y, InputBitmap0.GetPixel(x, y));
简而言之:
如何在 GPU 中为输入位图的每个像素点获取 GetPixel(),为输出位图位图的每个像素点设置像素点。
我认为您需要使用 byte[]
并将其分配到 GPU 上。 I've seen you asking around 这个答案还在制作中,我会在接下来几天有空时不断更新它。
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;
}
OutputBitmap.SetPixel(object_point_x, object_point_y, InputBitmap0.GetPixel(x, y))
这花了一些时间,但我终于破案了。
我们有两个 Bitmap
:一个用于输出 OutputBitmap
,另一个用于输入 InputBitmap0
让我们把这个任务分成几个部分:
- 为
x
做InputBitmap0.GetPixel()
,y
坐标 - 然后 ,
OutputBitmap.SetPixel()
换一个坐标object_point_x, object_point_y
Cudafy 不支持 Bitmap
或 Color
类型的数据。所以我将位图转换为 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
做上述工作(制作数组),因为我们将在 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_color
和 output_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];
}
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 ofinput_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()
)
我们现在知道 gpu 已经为我们的 OutputBitmap
填充了一个数组 (dev_output_rgba_color
)。
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
包含更新后的值。