使用Cuda在C中操纵BMP会返回黑色图片

时间:2019-06-24 18:08:14

标签: arrays image-processing bitmap cuda

所以我的任务是在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似乎存在问题,我不知道为什么。

0 个答案:

没有答案