forked from paulknysh/shaper
-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathshaper.cpp
175 lines (136 loc) · 4.88 KB
/
shaper.cpp
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
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
#include <vector>
#include <string>
#define STB_IMAGE_IMPLEMENTATION
#define STB_IMAGE_WRITE_IMPLEMENTATION
#include "stb_image.h"
#include "stb_image_write.h"
// contains pixel coordinates & RGB channels
typedef std::vector < std::vector < std::vector < unsigned char > > > image;
// function prototypes
std::vector < image > produce_subsections(image sec1, image sec2, int m, int w, int h);
image morph(image im1, image im2, int w, int h);
image arr_to_im(unsigned char * arr, int w, int h);
unsigned char * im_to_arr(image im, int w, int h);
int main() {
int n = 3;
int m = 10;
int w, h, bpp;
int i, j;
unsigned char * io;
std::vector < image > sections, subsections;
// read sections
for (i = 0; i < n; i++) {
io = stbi_load((std::to_string(i + 1) + ".png").c_str(), & w, & h, & bpp, 3);
sections.push_back(arr_to_im(io, w, h));
stbi_image_free(io);
}
// produce & save subsections
for (i = 0; i < n - 1; i++) {
subsections = produce_subsections(sections[i], sections[i + 1], m, w, h);
for (j = 0; j < m; j++) {
io = im_to_arr(subsections[j], w, h);
stbi_write_bmp((std::to_string(i + 1) + "_" + std::to_string(j + 1) + ".png").c_str(), w, h, 3, io);
delete[] io;
}
}
}
std::vector < image > produce_subsections(image sec1, image sec2, int m, int w, int h) {
int i;
std::vector < image > subsections, subsections_scaled;
// initialize
subsections.push_back(sec1);
subsections.push_back(sec2);
// iterate
int ncycles = 0;
while (pow(2, ncycles) - 1 < m) {
for (i = 0; i < pow(2, ncycles); i++) {
subsections.insert(subsections.begin() + (2 * i + 1), morph(subsections[2 * i], subsections[2 * i + 1], w, h));
}
ncycles++;
}
// rescale
for (i = 0; i < m + 2; i++) {
subsections_scaled.push_back(subsections[round(pow(2, ncycles) * (1. * i) / (m + 1))]);
}
// return subsections only
subsections_scaled.erase(subsections_scaled.begin());
subsections_scaled.erase(subsections_scaled.end());
return subsections_scaled;
}
image morph(image im1, image im2, int w, int h) {
int i, j;
image res = im1;
std::vector < std::vector < bool > > no_mismatch(h, std::vector < bool > (w, false));
std::vector < std::vector < bool > > mismatch = no_mismatch;
// initialize mismatch
for (i = 0; i < h; i++) {
for (j = 0; j < w; j++) {
if (im1[i][j][0] != im2[i][j][0] || im1[i][j][1] != im2[i][j][1] || im1[i][j][2] != im2[i][j][2]) {
mismatch[i][j] = true;
}
}
}
while (mismatch != no_mismatch) {
// right neighbors
for (i = 0; i < h; i++) {
for (j = 0; j < w - 1; j++) {
if (mismatch[i][j] == true && mismatch[i][j + 1] == false) {
res[i][j] = res[i][j + 1];
mismatch[i][j] = false;
}
}
}
// top neighbors
for (i = h - 1; i > 0; i--) {
for (j = 0; j < w; j++) {
if (mismatch[i][j] == true && mismatch[i - 1][j] == false) {
res[i][j] = res[i - 1][j];
mismatch[i][j] = false;
}
}
}
// left neighbors
for (i = 0; i < h; i++) {
for (j = w - 1; j > 0; j--) {
if (mismatch[i][j] == true && mismatch[i][j - 1] == false) {
res[i][j] = res[i][j - 1];
mismatch[i][j] = false;
}
}
}
// bottom neighbors
for (i = 0; i < h - 1; i++) {
for (j = 0; j < w; j++) {
if (mismatch[i][j] == true && mismatch[i + 1][j] == false) {
res[i][j] = res[i + 1][j];
mismatch[i][j] = false;
}
}
}
}
return res;
}
image arr_to_im(unsigned char * arr, int w, int h) {
int i, j;
image im(h, std::vector < std::vector < unsigned char > > (w, std::vector < unsigned char > (3, 0)));
for (i = 0; i < h; i++) {
for (j = 0; j < w; j++) {
im[i][j][0] = arr[3 * (i * w + j)];
im[i][j][1] = arr[3 * (i * w + j) + 1];
im[i][j][2] = arr[3 * (i * w + j) + 2];
}
}
return im;
}
unsigned char * im_to_arr(image im, int w, int h) {
int i, j;
unsigned char * arr = new unsigned char[w * h * 3];
for (i = 0; i < h; i++) {
for (j = 0; j < w; j++) {
arr[3 * (i * w + j)] = im[i][j][0];
arr[3 * (i * w + j) + 1] = im[i][j][1];
arr[3 * (i * w + j) + 2] = im[i][j][2];
}
}
return arr;
}