add laplace convolution to neighbor calculations
This commit is contained in:
parent
aad28da6a4
commit
7f8b65ac36
1 changed files with 27 additions and 5 deletions
32
resynth.c
32
resynth.c
|
@ -137,6 +137,7 @@ typedef struct {
|
||||||
double autism;
|
double autism;
|
||||||
int neighbors, tries;
|
int neighbors, tries;
|
||||||
int magic;
|
int magic;
|
||||||
|
bool weighted;
|
||||||
} Parameters;
|
} Parameters;
|
||||||
|
|
||||||
INLINE bool wrap_or_clip(const Parameters parameters, const Image image,
|
INLINE bool wrap_or_clip(const Parameters parameters, const Image image,
|
||||||
|
@ -223,23 +224,34 @@ static void make_offset_list(Resynth_state *s) {
|
||||||
sizeof(Coord), coord_compare);
|
sizeof(Coord), coord_compare);
|
||||||
}
|
}
|
||||||
|
|
||||||
INLINE void try_point(Resynth_state *s, const Coord point) {
|
INLINE int weight_at(const Coord point) {
|
||||||
|
if (point.x == 0 && point.y == 0) return 0;
|
||||||
|
// this is stable and accurate up to -N 37 (-R 9)
|
||||||
|
// 520 might work in place of 360 and provide more accuracy w/o overflows.
|
||||||
|
return 360 / (point.x * point.x + point.y * point.y);
|
||||||
|
}
|
||||||
|
|
||||||
|
INLINE void try_point(Resynth_state *s, const Coord point, bool weighted) {
|
||||||
// consider a candidate pixel for the best-fit by considering its neighbors.
|
// consider a candidate pixel for the best-fit by considering its neighbors.
|
||||||
int sum = 0;
|
int sum = 0;
|
||||||
|
|
||||||
for (int i = 0; i < s->n_neighbors; i++) {
|
for (int i = 0; i < s->n_neighbors; i++) {
|
||||||
Coord off_point = coord_add(point, s->neighbors[i]);
|
Coord off_point = coord_add(point, s->neighbors[i]);
|
||||||
|
|
||||||
|
int diff = 0;
|
||||||
if (off_point.x < 0 || off_point.y < 0 ||
|
if (off_point.x < 0 || off_point.y < 0 ||
|
||||||
off_point.x >= s->corpus.width || off_point.y >= s->corpus.height) {
|
off_point.x >= s->corpus.width || off_point.y >= s->corpus.height) {
|
||||||
sum += s->diff_table[0] * s->input_bytes;
|
diff = s->diff_table[0] * s->input_bytes;
|
||||||
} else if (i) {
|
} else if (i) {
|
||||||
const Pixel *corpus_pixel = image_atc(s->corpus, off_point);
|
const Pixel *corpus_pixel = image_atc(s->corpus, off_point);
|
||||||
const Pixel *data_pixel = s->neighbor_values[i].v;
|
const Pixel *data_pixel = s->neighbor_values[i].v;
|
||||||
for (int j = 0; j < s->input_bytes; j++) {
|
for (int j = 0; j < s->input_bytes; j++) {
|
||||||
sum += s->diff_table[256 + data_pixel[j] - corpus_pixel[j]];
|
diff += s->diff_table[256 + data_pixel[j] - corpus_pixel[j]];
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (weighted) diff *= weight_at(s->neighbors[i]);
|
||||||
|
sum += diff;
|
||||||
if (sum >= s->best) return;
|
if (sum >= s->best) return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -376,7 +388,7 @@ static void run(Resynth_state *s, Parameters parameters) {
|
||||||
// skip computing differences of points
|
// skip computing differences of points
|
||||||
// we've already done this iteration. not mandatory.
|
// we've already done this iteration. not mandatory.
|
||||||
if (*image_atc(s->tried, point) == i) continue;
|
if (*image_atc(s->tried, point) == i) continue;
|
||||||
try_point(s, point);
|
try_point(s, point, parameters.weighted);
|
||||||
*image_atc(s->tried, point) = i;
|
*image_atc(s->tried, point) = i;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -385,7 +397,7 @@ static void run(Resynth_state *s, Parameters parameters) {
|
||||||
// choosing the first couple pixels, since they have no neighbors.
|
// choosing the first couple pixels, since they have no neighbors.
|
||||||
// after that, this step is optional. it can improve subjective quality.
|
// after that, this step is optional. it can improve subjective quality.
|
||||||
for (int j = 0; j < parameters.tries && s->best != 0; j++) {
|
for (int j = 0; j < parameters.tries && s->best != 0; j++) {
|
||||||
try_point(s, s->corpus_points[rand() % sb_count(s->corpus_points)]);
|
try_point(s, s->corpus_points[rand() % sb_count(s->corpus_points)], parameters.weighted);
|
||||||
}
|
}
|
||||||
|
|
||||||
// finally, copy the best pixel to the output image.
|
// finally, copy the best pixel to the output image.
|
||||||
|
@ -442,6 +454,7 @@ int main(int argc, char *argv[]) {
|
||||||
Parameters parameters = {0};
|
Parameters parameters = {0};
|
||||||
parameters.v_tile = true;
|
parameters.v_tile = true;
|
||||||
parameters.h_tile = true;
|
parameters.h_tile = true;
|
||||||
|
parameters.weighted = false; // our extension
|
||||||
// blah = our default; // original resynthesizer default
|
// blah = our default; // original resynthesizer default
|
||||||
parameters.magic = 192; // 192 (3/4)
|
parameters.magic = 192; // 192 (3/4)
|
||||||
parameters.autism = 32. / 256.; // 30. / 256.
|
parameters.autism = 32. / 256.; // 30. / 256.
|
||||||
|
@ -494,6 +507,15 @@ int main(int argc, char *argv[]) {
|
||||||
" default: 0 [time(0)]")
|
" default: 0 [time(0)]")
|
||||||
seed = (unsigned long) kyaa_flag_arg;
|
seed = (unsigned long) kyaa_flag_arg;
|
||||||
|
|
||||||
|
KYAA_FLAG('w', "weighted",
|
||||||
|
" enables something like laplace convolution but not really\n"
|
||||||
|
" default: off")
|
||||||
|
parameters.weighted = true;
|
||||||
|
|
||||||
|
KYAA_FLAG('W', "unweighted",
|
||||||
|
" disables --weighted")
|
||||||
|
parameters.weighted = false;
|
||||||
|
|
||||||
KYAA_HELP(" {files...}\n"
|
KYAA_HELP(" {files...}\n"
|
||||||
" image files to open, resynthesize, and save as {filename}.resynth.png\n"
|
" image files to open, resynthesize, and save as {filename}.resynth.png\n"
|
||||||
" required default: [none]")
|
" required default: [none]")
|
||||||
|
|
Loading…
Add table
Reference in a new issue