-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathlab7.c
More file actions
129 lines (105 loc) · 2.85 KB
/
lab7.c
File metadata and controls
129 lines (105 loc) · 2.85 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
#include <stdlib.h>
#include <stdbool.h>
#include <string.h>
#include "png_wrapper.h"
struct Point {
uint32_t x, y;
};
static void binarization(struct Image img, unsigned char threshold)
{
for (size_t y = 0; y < img.height; y++)
for (size_t x = 0; x < img.width; x++)
img.pixels[y][x] = img.pixels[y][x] >= threshold ? 255 : 0;
}
static bool find_white_pixel(struct Image img, struct Point *pixel)
{
for (size_t y = 0; y < img.height; y++)
for (size_t x = 0; x < img.width; x++)
if (img.pixels[y][x])
{
pixel->x = x;
pixel->y = y;
return true;
}
return false;
}
static size_t segmentation(struct Image in, struct Image out)
{
size_t count = 0;
unsigned char prev_color = 0;
struct Point pixel;
while (find_white_pixel(in, &pixel))
{
unsigned char new_color = prev_color + 50 <= 255 ? prev_color + 50 : 50;
struct Image front = { in.width, in.height, NULL };
alloc_pixels(&front);
for (size_t y = 0; y < front.height; y++)
for (size_t x = 0; x < front.width; x++)
front.pixels[y][x] = 0;
front.pixels[pixel.y][pixel.x] = 1;
while (true)
{
struct Point pix;
if (!find_white_pixel(front, &pix))
break;
front.pixels[pix.y][pix.x] = 0;
if (in.pixels[pix.y][pix.x])
{
in.pixels[pix.y][pix.x] = 0;
out.pixels[pix.y][pix.x] = new_color;
if (pix.y > 0
&& in.pixels[pix.y - 1][pix.x ])
front.pixels[pix.y - 1][pix.x ] = 1;
if (pix.x > 0
&& in.pixels[pix.y ][pix.x - 1])
front.pixels[pix.y ][pix.x - 1] = 1;
if (pix.y < in.height - 1
&& in.pixels[pix.y + 1][pix.x ])
front.pixels[pix.y + 1][pix.x ] = 1;
if (pix.x < in.width - 1
&& in.pixels[pix.y ][pix.x + 1])
front.pixels[pix.y ][pix.x + 1] = 1;
}
}
prev_color = new_color;
count++;
free_pixels(front);
}
return count;
}
int main(int argc, char * const argv[])
{
if (argc < 3 || argc > 4)
error("usage: %s <input_file> [<output_file>] <threshold (0-255)>",
argv[0]);
char *input_filename = argv[1];
char *output_filename;
char *s_threshold;
if (argc == 4)
{
output_filename = argv[2];
s_threshold = argv[3];
}
else
{
output_filename = alloca(strlen(input_filename) + sizeof("_out.png"));
strcpy(output_filename, input_filename);
strcat(output_filename, "_out.png");
s_threshold = argv[2];
}
int threshold = atoi(s_threshold);
if (threshold < 0 || threshold > 255)
error("wrong threshold (%d)", threshold);
struct Image in = read_grayscale_png(input_filename);
printf("Input file \"%s\" opened (width = %u, height = %u)\n",
input_filename, in.width, in.height);
binarization(in, (unsigned char) threshold);
struct Image out = { in.width, in.height, NULL };
alloc_pixels(&out);
size_t s = segmentation(in, out);
free_pixels(in);
printf("%lu segments\n", s);
write_grayscale_png(out, output_filename);
free_pixels(out);
return 0;
}