forked from gsilber/CISC372_picProject
-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathimage_openmp.c
More file actions
130 lines (116 loc) · 5.5 KB
/
image_openmp.c
File metadata and controls
130 lines (116 loc) · 5.5 KB
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
123
124
125
126
127
128
129
130
#include <stdio.h>
#include <stdint.h>
#include <time.h>
#include <string.h>
#include <stdlib.h>
#include <omp.h>
#include "image.h"
#define STB_IMAGE_IMPLEMENTATION
#include "stb_image.h"
#define STB_IMAGE_WRITE_IMPLEMENTATION
#include "stb_image_write.h"
//An array of kernel matrices to be used for image convolution.
//The indexes of these match the enumeration from the header file. ie. algorithms[BLUR] returns the kernel corresponding to a box blur.
Matrix algorithms[]={
{{0,-1,0},{-1,4,-1},{0,-1,0}},
{{0,-1,0},{-1,5,-1},{0,-1,0}},
{{1/9.0,1/9.0,1/9.0},{1/9.0,1/9.0,1/9.0},{1/9.0,1/9.0,1/9.0}},
{{1.0/16,1.0/8,1.0/16},{1.0/8,1.0/4,1.0/8},{1.0/16,1.0/8,1.0/16}},
{{-2,-1,0},{-1,1,1},{0,1,2}},
{{0,0,0},{0,1,0},{0,0,0}}
};
//getPixelValue - Computes the value of a specific pixel on a specific channel using the selected convolution kernel
//Parameters: srcImage: An Image struct populated with the image being convoluted
// x: The x coordinate of the pixel
// y: The y coordinate of the pixel
// bit: The color channel being manipulated
// algorithm: The 3x3 kernel matrix to use for the convolution
//Returns: The new value for this x,y pixel and bit channel
uint8_t getPixelValue(Image* srcImage,int x,int y,int bit,Matrix algorithm){
int px,mx,py,my,i,span;
span=srcImage->width*srcImage->bpp;
// for the edge pixels, just reuse the edge pixel
px=x+1; py=y+1; mx=x-1; my=y-1;
if (mx<0) mx=0;
if (my<0) my=0;
if (px>=srcImage->width) px=srcImage->width-1;
if (py>=srcImage->height) py=srcImage->height-1;
uint8_t result=
algorithm[0][0]*srcImage->data[Index(mx,my,srcImage->width,bit,srcImage->bpp)]+
algorithm[0][1]*srcImage->data[Index(x,my,srcImage->width,bit,srcImage->bpp)]+
algorithm[0][2]*srcImage->data[Index(px,my,srcImage->width,bit,srcImage->bpp)]+
algorithm[1][0]*srcImage->data[Index(mx,y,srcImage->width,bit,srcImage->bpp)]+
algorithm[1][1]*srcImage->data[Index(x,y,srcImage->width,bit,srcImage->bpp)]+
algorithm[1][2]*srcImage->data[Index(px,y,srcImage->width,bit,srcImage->bpp)]+
algorithm[2][0]*srcImage->data[Index(mx,py,srcImage->width,bit,srcImage->bpp)]+
algorithm[2][1]*srcImage->data[Index(x,py,srcImage->width,bit,srcImage->bpp)]+
algorithm[2][2]*srcImage->data[Index(px,py,srcImage->width,bit,srcImage->bpp)];
return result;
}
//convolute: Applies a kernel matrix to an image using OpenMP
//Parameters: srcImage: The image being convoluted
// destImage: A pointer to a pre-allocated structure to receive the convoluted image
// algorithm: The kernel matrix to use for the convolution
//Returns: Nothing
void convolute(Image* srcImage,Image* destImage,Matrix algorithm){
int row,pix,bit;
// Parallelize the outer loop (rows) using OpenMP
// Each thread processes different rows independently
#pragma omp parallel for private(pix, bit) schedule(dynamic)
for (row=0;row<srcImage->height;row++){
for (pix=0;pix<srcImage->width;pix++){
for (bit=0;bit<srcImage->bpp;bit++){
destImage->data[Index(pix,row,srcImage->width,bit,srcImage->bpp)]=
getPixelValue(srcImage,pix,row,bit,algorithm);
}
}
}
}
//Usage: Prints usage information for the program
//Returns: -1
int Usage(){
printf("Usage: image <filename> <type>\n\twhere type is one of (edge,sharpen,blur,gauss,emboss,identity)\n");
return -1;
}
//GetKernelType: Converts the string name of a convolution into a value from the KernelTypes enumeration
//Parameters: type: A string representation of the type
//Returns: an appropriate entry from the KernelTypes enumeration, defaults to IDENTITY
enum KernelTypes GetKernelType(char* type){
if (!strcmp(type,"edge")) return EDGE;
else if (!strcmp(type,"sharpen")) return SHARPEN;
else if (!strcmp(type,"blur")) return BLUR;
else if (!strcmp(type,"gauss")) return GAUSE_BLUR;
else if (!strcmp(type,"emboss")) return EMBOSS;
else return IDENTITY;
}
//main:
//argv is expected to take 2 arguments. First is the source file name (can be jpg, png, bmp, tga). Second is the lower case name of the algorithm.
int main(int argc,char** argv){
long t1,t2;
t1=time(NULL);
stbi_set_flip_vertically_on_load(0);
if (argc!=3) return Usage();
char* fileName=argv[1];
if (!strcmp(argv[1],"pic4.jpg")&&!strcmp(argv[2],"gauss")){
printf("You have applied a gaussian filter to Gauss which has caused a tear in the time-space continuum.\n");
}
enum KernelTypes type=GetKernelType(argv[2]);
Image srcImage,destImage;
srcImage.data=stbi_load(fileName,&srcImage.width,&srcImage.height,&srcImage.bpp,0);
if (!srcImage.data){
printf("Error loading file %s.\n",fileName);
return -1;
}
destImage.bpp=srcImage.bpp;
destImage.height=srcImage.height;
destImage.width=srcImage.width;
destImage.data=malloc(sizeof(uint8_t)*destImage.width*destImage.bpp*destImage.height);
printf("Using OpenMP with %d threads\n", omp_get_max_threads());
convolute(&srcImage,&destImage,algorithms[type]);
stbi_write_png("output.png",destImage.width,destImage.height,destImage.bpp,destImage.data,destImage.bpp*destImage.width);
stbi_image_free(srcImage.data);
free(destImage.data);
t2=time(NULL);
printf("Took %ld seconds\n",t2-t1);
return 0;
}