-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathc03s02_rgbToGrayscale.cu
122 lines (96 loc) · 3.48 KB
/
c03s02_rgbToGrayscale.cu
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
#include <stdio.h>
#include <jpeglib.h>
#include <cuda_runtime.h>
__host__
void loadImage(const char* filename, unsigned char** image, int* width, int* height) {
struct jpeg_decompress_struct cinfo;
struct jpeg_error_mgr jerr;
FILE* infile;
JSAMPARRAY buffer;
// Open file
if ((infile = fopen(filename, "rb")) == NULL) {
fprintf(stderr, "Can't open %s\n", filename);
exit(1);
}
cinfo.err = jpeg_std_error(&jerr);
jpeg_create_decompress(&cinfo);
jpeg_stdio_src(&cinfo, infile);
jpeg_read_header(&cinfo, TRUE);
jpeg_start_decompress(&cinfo);
*width = cinfo.output_width;
*height = cinfo.output_height;
*image = (unsigned char*)malloc(cinfo.output_width * cinfo.output_height * cinfo.output_components);
buffer = (*cinfo.mem->alloc_sarray)((j_common_ptr)&cinfo, JPOOL_IMAGE, cinfo.output_width * cinfo.output_components, 1);
while (cinfo.output_scanline < cinfo.output_height) {
jpeg_read_scanlines(&cinfo, buffer, 1);
memcpy(*image + (cinfo.output_scanline - 1) * cinfo.output_width * cinfo.output_components, buffer[0], cinfo.output_width * cinfo.output_components);
}
jpeg_finish_decompress(&cinfo);
jpeg_destroy_decompress(&cinfo);
fclose(infile);
}
__host__
void saveGrayJPEG(const char* filename, unsigned char* grayData, int width, int height) {
struct jpeg_compress_struct cinfo;
struct jpeg_error_mgr jerr;
FILE* outfile;
JSAMPROW row_pointer[1];
cinfo.err = jpeg_std_error(&jerr);
jpeg_create_compress(&cinfo);
if ((outfile = fopen(filename, "wb")) == NULL) {
fprintf(stderr, "Can't open %s for writing\n", filename);
exit(1);
}
jpeg_stdio_dest(&cinfo, outfile);
cinfo.image_width = width;
cinfo.image_height = height;
cinfo.input_components = 1;
cinfo.in_color_space = JCS_GRAYSCALE;
jpeg_set_defaults(&cinfo);
jpeg_set_quality(&cinfo, 75, TRUE);
jpeg_start_compress(&cinfo, TRUE);
while (cinfo.next_scanline < cinfo.image_height) {
row_pointer[0] = &grayData[cinfo.next_scanline * width];
jpeg_write_scanlines(&cinfo, row_pointer, 1);
}
jpeg_finish_compress(&cinfo);
fclose(outfile);
jpeg_destroy_compress(&cinfo);
}
__global__
void convertRGBPixelToGrayscale(
unsigned char *gray,
unsigned char *rgb,
int width,
int height
) {
unsigned int row = blockDim.y * blockIdx.y + threadIdx.y;
unsigned int col = blockDim.x * blockIdx.x + threadIdx.x;
if (col < width && row < height) {
int i = row * width + col;
unsigned char r = rgb[3 * i];
unsigned char g = rgb[3 * i + 1];
unsigned char b = rgb[3 * i + 2];
gray[i] = r*0.21f + g*0.72f + b*0.07f;
}
}
int main() {
int width, height;
unsigned char *rgb_h, *rgb_d, *gray_d;
loadImage("elf_rgb.jpeg", &rgb_h, &width, &height);
cudaMalloc(&rgb_d, width * height * 3);
cudaMalloc(&gray_d, width * height);
cudaMemcpy(rgb_d, rgb_h, width * height * 3, cudaMemcpyHostToDevice);
dim3 dimBlock(16, 16);
dim3 dimGrid((width + 15) / 16, (height + 15) / 16);
convertRGBPixelToGrayscale<<<dimGrid, dimBlock>>>(gray_d, rgb_d, width, height);
unsigned char* gray_h = (unsigned char*)malloc(width * height);
cudaMemcpy(gray_h, gray_d, width * height, cudaMemcpyDeviceToHost);
// Save to JPEG
saveGrayJPEG("elf_gray.jpeg", gray_h, width, height);
cudaFree(rgb_d);
cudaFree(gray_d);
free(rgb_h);
free(gray_h);
return 0;
}