Skip to content

Commit f0313da

Browse files
committed
Initial commit (serial version)
0 parents  commit f0313da

12 files changed

+10187
-0
lines changed

CMakeLists.txt

+9
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
cmake_minimum_required(VERSION 3.20)
2+
project(Image_Kernel_Processing_OpenMP)
3+
4+
set(CMAKE_C_STANDARD 11)
5+
6+
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -fopenmp")
7+
8+
add_executable(Image_Kernel_Processing_OpenMP main.c Image.h Image.c Utils.h Utils.c stb_image.h stb_image_write.h Kernel.c Kernel.h Processing.c Processing.h)
9+
target_link_libraries(Image_Kernel_Processing_OpenMP m)

Image.c

+48
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,48 @@
1+
//
2+
// Created by kevin on 18/09/21.
3+
//
4+
5+
#include "Image.h"
6+
#include <stdlib.h>
7+
8+
Image *Image_new(int width, int height, int channels, unsigned char *data) {
9+
Image *img = (Image *) malloc(sizeof(Image));
10+
11+
Image_setWidth(img, width);
12+
Image_setHeight(img, height);
13+
Image_setChannels(img, channels);
14+
Image_setPitch(img, width * channels);
15+
16+
Image_setData(img, data);
17+
return img;
18+
}
19+
20+
Image *Image_new_empty(int width, int height, int channels) {
21+
unsigned char *data = (unsigned char *) malloc(sizeof(unsigned char) * width * height * channels);
22+
return Image_new(width, height, channels, data);
23+
}
24+
25+
void Image_delete(Image *img) {
26+
if (img != NULL) {
27+
if (Image_getData(img) != NULL) {
28+
free(Image_getData(img));
29+
}
30+
free(img);
31+
}
32+
}
33+
34+
void Image_setPixel(Image *img, int x, int y, int c, unsigned char val) {
35+
unsigned char *data = Image_getData(img);
36+
int channels = Image_getChannels(img);
37+
int pitch = Image_getPitch(img);
38+
39+
data[y * pitch + x * channels + c] = val;
40+
}
41+
42+
unsigned char Image_getPixel(Image *img, int x, int y, int c) {
43+
unsigned char *data = Image_getData(img);
44+
int channels = Image_getChannels(img);
45+
int pitch = Image_getPitch(img);
46+
47+
return data[y * pitch + x * channels + c];
48+
}

Image.h

+86
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,86 @@
1+
//
2+
// Created by kevin on 18/09/21.
3+
//
4+
5+
#ifndef IMAGE_KERNEL_PROCESSING_IMAGE_H
6+
#define IMAGE_KERNEL_PROCESSING_IMAGE_H
7+
8+
9+
/**
10+
* Represents an image with data and its metadata
11+
*/
12+
typedef struct {
13+
int width;
14+
int height;
15+
int channels;
16+
int pitch;
17+
unsigned char *data;
18+
} Image;
19+
20+
/**
21+
* RGB channels
22+
*/
23+
#define tri_color 3
24+
/**
25+
* Gray-scale channel
26+
*/
27+
#define monochrome 1
28+
29+
#define Image_getWidth(img) ((img)->width)
30+
#define Image_getHeight(img) ((img)->height)
31+
#define Image_getChannels(img) ((img)->channels)
32+
#define Image_getPitch(img) ((img)->pitch)
33+
#define Image_getData(img) ((img)->data)
34+
35+
#define Image_setWidth(img, val) (Image_getWidth(img) = (val))
36+
#define Image_setHeight(img, val) (Image_getHeight(img) = (val))
37+
#define Image_setChannels(img, val) (Image_getChannels(img) = (val))
38+
#define Image_setPitch(img, val) (Image_getPitch(img) = (val))
39+
#define Image_setData(img, val) (Image_getData(img) = (val))
40+
41+
/**
42+
* Creates a new image from data and metadata
43+
* @param width
44+
* @param height
45+
* @param channels
46+
* @param data
47+
* @return Image
48+
*/
49+
Image *Image_new(int width, int height, int channels, unsigned char *data);
50+
51+
/**
52+
* Creates a new empty image with only metadata
53+
* @param width
54+
* @param height
55+
* @param channels
56+
* @return
57+
*/
58+
Image *Image_new_empty(int width, int height, int channels);
59+
60+
/**
61+
* Returns the value of a channel of a given pixel
62+
* @param img Image
63+
* @param x x-axis coordinate
64+
* @param y y-axis coordinate
65+
* @param c channel
66+
* @return value
67+
*/
68+
unsigned char Image_getPixel(Image *img, int x, int y, int c);
69+
70+
/**
71+
* Sets the value of a channel of a given pixel
72+
* @param img Image
73+
* @param x x-axis coordinate
74+
* @param y y-axis coordinate
75+
* @param c channel
76+
* @param val value
77+
*/
78+
void Image_setPixel(Image *img, int x, int y, int c, unsigned char val);
79+
80+
/**
81+
* Frees the mem allocation of an image
82+
* @param img Image
83+
*/
84+
void Image_delete(Image *img);
85+
86+
#endif //IMAGE_KERNEL_PROCESSING_IMAGE_H

Kernel.c

+95
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,95 @@
1+
//
2+
// Created by kevin on 19/09/21.
3+
//
4+
5+
#include <malloc.h>
6+
#include "Kernel.h"
7+
8+
Kernel *Kernel_new(int size, double weight, unsigned long long int *coefficients) {
9+
Kernel *krn = (Kernel *) malloc(sizeof(Kernel));
10+
11+
Kernel_setSize(krn, size);
12+
Kernel_setWeight(krn, weight);
13+
Kernel_setCoefficients(krn, coefficients);
14+
15+
return krn;
16+
}
17+
18+
Kernel *Kernel_newEmpty(int size, double weight) {
19+
unsigned long long int *coefficients = (unsigned long long int *) malloc(
20+
sizeof(unsigned long long int) * size * size);
21+
return Kernel_new(size, weight, coefficients);
22+
}
23+
24+
unsigned long long int Kernel_getCoefficient(Kernel *krn, int x, int y) {
25+
unsigned long long int *coefficients = Kernel_getCoefficients(krn);
26+
int size = Kernel_getSize(krn);
27+
return coefficients[y * size + x];
28+
}
29+
30+
void Kernel_setCoefficient(Kernel *krn, int x, int y, unsigned long long int coefficient) {
31+
unsigned long long int *coefficients = Kernel_getCoefficients(krn);
32+
int size = Kernel_getSize(krn);
33+
34+
coefficients[y * size + x] = coefficient;
35+
}
36+
37+
void Kernel_delete(Kernel *krn) {
38+
if (krn != NULL) {
39+
if (Kernel_getCoefficients(krn) != NULL) {
40+
free(Kernel_getCoefficients(krn));
41+
}
42+
free(krn);
43+
}
44+
}
45+
46+
Kernel *Kernel_boxBlur(int size) {
47+
Kernel *krn = Kernel_newEmpty(size, 1.0 / (double) (size * size));
48+
49+
for (int i = 0; i < size * size; i++) {
50+
Kernel_getCoefficients(krn)[i] = 1;
51+
}
52+
53+
return krn;
54+
}
55+
56+
Kernel *Kernel_identity(int size) {
57+
Kernel *krn = Kernel_newEmpty(size, unnormalized);
58+
59+
Kernel_getCoefficients(krn)[(size * size - 1) / 2] = 1;
60+
61+
return krn;
62+
}
63+
64+
Kernel *Kernel_gaussianBlur(int size) {
65+
unsigned long long int coef = 0;
66+
unsigned long long int sum = 0;
67+
unsigned long long int *coefficients = (unsigned long long int *) malloc(sizeof(unsigned long long int) * size);
68+
for (int j = 0; j < size; j++) {
69+
if (j == 0)
70+
coef = 1;
71+
else
72+
coef = coef * (size - j) / j;
73+
coefficients[j] = coef;
74+
sum += coef;
75+
}
76+
77+
Kernel *krn = Kernel_newEmpty(size, 1.0 / (double) (sum * sum));
78+
79+
for (int i = 0; i < size * size; i++) {
80+
int col = i % size;
81+
int row = i / size;
82+
Kernel_getCoefficients(krn)[i] = (coefficients[row] * coefficients[col]);
83+
}
84+
85+
free(coefficients);
86+
return krn;
87+
}
88+
89+
void Kernel_normalize(Kernel *krn) {
90+
unsigned long long int sum = 0;
91+
for (int i = 0; i < krn->size * krn->size; i++) {
92+
sum += krn->coefficients[i];
93+
}
94+
krn->weight = 1.0 / (double) sum;
95+
}

Kernel.h

+108
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,108 @@
1+
//
2+
// Created by kevin on 19/09/21.
3+
//
4+
5+
#ifndef IMAGE_KERNEL_PROCESSING_KERNEL_H
6+
#define IMAGE_KERNEL_PROCESSING_KERNEL_H
7+
8+
/**
9+
* Represents a Kernel matrix
10+
*/
11+
typedef struct {
12+
/**
13+
* radius of the kernel
14+
*/
15+
int size;
16+
/**
17+
* scalar for normalization
18+
*/
19+
double weight;
20+
/**
21+
* kernel's coefficients
22+
*/
23+
unsigned long long int *coefficients;
24+
} Kernel;
25+
26+
/**
27+
* unnormalized weight
28+
*/
29+
#define unnormalized 1
30+
31+
#define Kernel_getSize(krn) ((krn)->size)
32+
#define Kernel_getWeight(krn) ((krn)->weight)
33+
#define Kernel_getCoefficients(krn) ((krn)->coefficients)
34+
35+
#define Kernel_setSize(krn, val) (Kernel_getSize(krn) = (val))
36+
#define Kernel_setWeight(krn, val) (Kernel_getWeight(krn) = (val))
37+
#define Kernel_setCoefficients(krn, val) (Kernel_getCoefficients(krn) = (val))
38+
39+
/**
40+
* Creates a new Kernel with a given coefficients and metadata
41+
* @param size kernel's radius
42+
* @param weight scalar weight
43+
* @param coefficients matrix values
44+
* @return Kernel
45+
*/
46+
Kernel *Kernel_new(int size, double weight, unsigned long long int *coefficients);
47+
48+
/**
49+
* Creates a new Kernel with only metadata
50+
* @param size kernel's radius
51+
* @param weight scalar weight
52+
* @return Kernel
53+
*/
54+
Kernel *Kernel_newEmpty(int size, double weight);
55+
56+
/**
57+
* Returns a kernel's value
58+
* @param krn Kernel
59+
* @param x x index
60+
* @param y y index
61+
* @return coefficient
62+
*/
63+
unsigned long long int Kernel_getCoefficient(Kernel *krn, int x, int y);
64+
65+
/**
66+
* Sets a kernel's value
67+
* @param krn Kernel
68+
* @param x x index
69+
* @param y y index
70+
* @param coefficient value
71+
*/
72+
void Kernel_setCoefficient(Kernel *krn, int x, int y, unsigned long long int coefficient);
73+
74+
/**
75+
* Frees the mem allocation of a Kernel
76+
* @param krn Kernel
77+
*/
78+
void Kernel_delete(Kernel *krn);
79+
80+
/**
81+
* Creates a pre-built Kernel for box-blur effect
82+
* @param size radius
83+
* @return Kernel
84+
*/
85+
Kernel *Kernel_boxBlur(int size);
86+
87+
/**
88+
* FOR TEST PURPOSE ONLY
89+
* Creates a pre-built Kernel for identity
90+
* @param size radius
91+
* @return Kernel
92+
*/
93+
Kernel *Kernel_identity(int size);
94+
95+
/**
96+
* Creates a pre-built Kernel for approximate gaussian-blur effect
97+
* @param size radius
98+
* @return Kernel
99+
*/
100+
Kernel *Kernel_gaussianBlur(int size);
101+
102+
/**
103+
* Normalizes the weight
104+
* @param krn
105+
*/
106+
void Kernel_normalize(Kernel *krn);
107+
108+
#endif //IMAGE_KERNEL_PROCESSING_KERNEL_H

Processing.c

+40
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,40 @@
1+
//
2+
// Created by kevin on 26/09/21.
3+
//
4+
5+
#include "Processing.h"
6+
7+
Image *process(Image *img, Kernel *krn) {
8+
Image *res = Image_new_empty(img->width, img->height, img->channels);
9+
10+
for (int iy = 0; iy < img->height; iy++) {
11+
for (int ix = 0; ix < img->width; ix++) {
12+
for (int ic = 0; ic < img->channels; ic++) {
13+
unsigned long long int newVal = 0;
14+
for (int ky = 0; ky < krn->size; ky++) {
15+
for (int kx = 0; kx < krn->size; kx++) {
16+
int kCenter = krn->size / 2;
17+
int dx = kx - kCenter;
18+
int dy = ky - kCenter;
19+
int px = ix + dx;
20+
int py = iy + dy;
21+
22+
if (px < 0 || px >= img->width) { // edge handling: extend
23+
px = (px < 0) ? 0 : (img->width - 1);
24+
}
25+
if (py < 0 || py >= img->height) {
26+
py = (py < 0) ? 0 : (img->height - 1);
27+
}
28+
29+
newVal += (unsigned long long int) Image_getPixel(img, px, py, ic) *
30+
Kernel_getCoefficient(krn, ky, kx);
31+
}
32+
}
33+
newVal = (unsigned long long int) ((long double) newVal * krn->weight);
34+
Image_setPixel(res, ix, iy, ic, (unsigned char) newVal);
35+
}
36+
}
37+
}
38+
39+
return res;
40+
}

0 commit comments

Comments
 (0)