所以我的任务是在C语言中使用CUDA操纵BMP。
这是我的代码:
#include <stdlib.h>
#include <stdio.h>
#include <cuda_runtime.h>
#include <device_launch_parameters.h>
#define BLOCKSIZE 256
#define GRIDSIZE 8192
#define WIDTH 46
#define HEIGHT 46
// VALUES = WIDTH * HEIGHT * 3 (Since each Pixel owns three colorvalues)
#define VALUES 6348
// Filter using grid stride loop
__global__
void filter(int *a)
{
for (int i = blockIdx.x * blockDim.x + threadIdx.x; i < WIDTH*HEIGHT*3; i += blockDim.x * gridDim.x)
{
a[i] = a[i] + 2;
}
}
int main() {
int width = WIDTH;
int height = HEIGHT;
int colors[VALUES];
// Read in BMP
FILE *streamIn;
streamIn = fopen("testpic.bmp", "r");
if (streamIn == (FILE *)0) {
printf("Fehler beim Lesen der Bilddatei.\n");
system("pause");
return EXIT_FAILURE;
}
// Ignore Bitmap-Header (54 Bytes)
int byte;
for (int i = 0; i < 54; i++)
byte = getc(streamIn);
// Read Pixels
for (int i = 0; i < VALUES; i++)
colors[i] = getc(streamIn);
// Close Filestream
fclose(streamIn);
// Write Pixels into the Device Memory
int *colors_d;
size_t arraysize = width*height * 3 * sizeof(int);
cudaMalloc((void**)&colors_d, arraysize);
cudaMemcpy(colors_d, colors, arraysize, cudaMemcpyHostToDevice);
// Apply Filter
filter <<<256,256>>> (colors_d);
// Write Pixels back into Hostmemory
cudaMemcpy(colors, colors_d, arraysize, cudaMemcpyDeviceToHost);
// Save BMP
// Source: https://stackoverflow.com/a/2654860/11378334
// Header-Informations
unsigned char bmpfileheader[14] = { 'B','M', 0,0,0,0, 0,0, 0,0, 54,0,0,0 };
unsigned char bmpinfoheader[40] = { 40,0,0,0, 0,0,0,0, 0,0,0,0, 1,0, 24,0 };
unsigned char bmppad[3] = { 0,0,0 };
// Size of BMP (54 Bytes for the BMP-Header)
int filesize = 54 + 3 * WIDTH * HEIGHT;
// Configure BMP-Header
bmpfileheader[2] = (unsigned char)(filesize);
bmpfileheader[3] = (unsigned char)(filesize >> 8);
bmpfileheader[4] = (unsigned char)(filesize >> 16);
bmpfileheader[5] = (unsigned char)(filesize >> 24);
bmpinfoheader[4] = (unsigned char)(width);
bmpinfoheader[5] = (unsigned char)(width >> 8);
bmpinfoheader[6] = (unsigned char)(width >> 16);
bmpinfoheader[7] = (unsigned char)(width >> 24);
bmpinfoheader[8] = (unsigned char)(height);
bmpinfoheader[9] = (unsigned char)(height >> 8);
bmpinfoheader[10] = (unsigned char)(height >> 16);
bmpinfoheader[11] = (unsigned char)(height >> 24);
// Create Filestream
FILE *streamOut;
streamOut = fopen("testpic.bmp", "wb");
fwrite(bmpfileheader, 1, 14, streamOut);
fwrite(bmpinfoheader, 1, 40, streamOut);
// Check if Pixelcolorvalues are < 0 or > 255
for (int i = 0; i < VALUES; i++) {
if (colors[i] < 0)
colors[i] = 0;
else if (colors[i] > 255)
colors[i] = 255;
}
// Write Pixels
for (int i = 0; i<height; i++)
{
fwrite(colors + (width*(height - i - 1) * 3), 3, width, streamOut);
fwrite(bmppad, 1, (4 - (width * 3) % 4) % 4, streamOut);
}
// Close FileStream
fclose(streamOut);
cudaFree(colors_d);
system("pause");
return EXIT_SUCCESS;
}
因此,如您所见,我首先从文件系统中读取了bmp文件(24位)。 然后,在忽略标题之后,我将具有3个颜色通道的像素数据写入一维数组(以便使用CUDA进行更好的处理)。
之后,我将阵列复制到GPU设备上并进行简单的计算(在这种情况下,我只需将每个颜色值加2)即可。
然后,我将数组返回到主机内存,生成一个BMP-Header,并将带有新的pixeldata的该头作为bmp写回到文件系统上。
代码本身不返回任何错误,但是无论输出什么图片,我都会得到一张黑色的图片。
所以cuda-stuff似乎还不错,但实际上bmp- Saving-progress似乎存在问题,我不知道为什么。