the algorithm now saves the best direction for every node, while generating the distances array
This commit is contained in:
parent
9e4b53b74f
commit
701fccdf65
Binary file not shown.
After Width: | Height: | Size: 5.3 KiB |
86
main.c
86
main.c
|
@ -7,17 +7,20 @@
|
||||||
#include <imago2.h>
|
#include <imago2.h>
|
||||||
#include "gfx.h"
|
#include "gfx.h"
|
||||||
|
|
||||||
#define DEBUG_BUILD 0
|
|
||||||
|
|
||||||
#define MASK_MULTIPLIER 50
|
#define MASK_MULTIPLIER 50
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
int32_t distance;
|
||||||
|
int8_t direction;
|
||||||
|
} distance_T;
|
||||||
|
|
||||||
typedef struct {
|
typedef struct {
|
||||||
uint32_t width;
|
uint32_t width;
|
||||||
uint32_t height;
|
uint32_t height;
|
||||||
uint32_t new_width;
|
uint32_t new_width;
|
||||||
uint32_t new_height;
|
uint32_t new_height;
|
||||||
uint32_t* buffer;
|
uint32_t* buffer;
|
||||||
int32_t* dist_buffer;
|
distance_T* dist_buffer;
|
||||||
uint32_t* mask_buffer;
|
uint32_t* mask_buffer;
|
||||||
} image_T;
|
} image_T;
|
||||||
|
|
||||||
|
@ -48,7 +51,7 @@ image_T* image_load(const char* filename, const char* filename_mask) {
|
||||||
image_T* image = malloc(sizeof(image_T));
|
image_T* image = malloc(sizeof(image_T));
|
||||||
image->mask_buffer = img_load_pixels(filename_mask, (int*)&image->width, (int*)&image->height, IMG_FMT_RGBA32);
|
image->mask_buffer = img_load_pixels(filename_mask, (int*)&image->width, (int*)&image->height, IMG_FMT_RGBA32);
|
||||||
image->buffer = img_load_pixels(filename, (int*)&image->width, (int*)&image->height, IMG_FMT_RGBA32);
|
image->buffer = img_load_pixels(filename, (int*)&image->width, (int*)&image->height, IMG_FMT_RGBA32);
|
||||||
image->dist_buffer = calloc(image->width * image->height, sizeof(uint32_t));
|
image->dist_buffer = calloc(image->width * image->height, sizeof(distance_T));
|
||||||
image->new_width = image->width;
|
image->new_width = image->width;
|
||||||
image->new_height = image->height;
|
image->new_height = image->height;
|
||||||
}
|
}
|
||||||
|
@ -63,24 +66,24 @@ void image_destruct(image_T* image) {
|
||||||
}
|
}
|
||||||
|
|
||||||
void image_calculate_dist_buffer(image_T* image) {
|
void image_calculate_dist_buffer(image_T* image) {
|
||||||
memset(image->dist_buffer, 0, image->height * image->width * sizeof(int32_t));
|
memset(image->dist_buffer, 0, image->width * sizeof(distance_T));
|
||||||
|
|
||||||
uint32_t* last_row = image->buffer;
|
uint32_t* last_row = image->buffer;
|
||||||
uint32_t* pixel_row = &last_row[image->width];
|
uint32_t* pixel_row = &last_row[image->width];
|
||||||
int32_t* dist_last_row = image->dist_buffer;
|
distance_T* dist_last_row = image->dist_buffer;
|
||||||
int32_t* dist_pixel_row = &dist_last_row[image->width];
|
distance_T* dist_pixel_row = &dist_last_row[image->width];
|
||||||
|
|
||||||
for (int y = 1; y < image->new_height; y++) {
|
for (int y = 1; y < image->new_height; y++) {
|
||||||
for (int x = 0; x < image->new_width; x++) {
|
for (int x = 0; x < image->new_width; x++) {
|
||||||
uint32_t pixel = pixel_row[x];
|
uint32_t pixel = pixel_row[x];
|
||||||
|
|
||||||
int32_t shortest_dist;
|
distance_T shortest_dist;
|
||||||
bool found_dist = false;
|
bool found_dist = false;
|
||||||
for (int i = (x > 0 ? -1 : 0); i < (x < image->new_width-1 ? 2 : 1); i++) {
|
for (int i = (x > 0 ? -1 : 0); i < (x < image->new_width-1 ? 2 : 1); i++) {
|
||||||
int32_t dist = pixel_distance(pixel, last_row[x + i], image->mask_buffer[(y * image->width) + x + i]) + dist_last_row[x + i];
|
int32_t dist = pixel_distance(pixel, last_row[x + i], image->mask_buffer[(y * image->width) + x + i]) + dist_last_row[x + i].distance;
|
||||||
|
|
||||||
if (!found_dist || shortest_dist > dist) {
|
if (!found_dist || shortest_dist.distance > dist) {
|
||||||
shortest_dist = dist;
|
shortest_dist = (distance_T){dist, (int8_t)i};
|
||||||
found_dist = true;
|
found_dist = true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -96,13 +99,13 @@ void image_calculate_dist_buffer(image_T* image) {
|
||||||
}
|
}
|
||||||
|
|
||||||
uint32_t image_find_best_line(image_T* image) {
|
uint32_t image_find_best_line(image_T* image) {
|
||||||
int32_t* row = &image->dist_buffer[(image->new_height-1) * image->width];
|
distance_T* row = &image->dist_buffer[(image->new_height-1) * image->width];
|
||||||
uint32_t line_id = 0;
|
uint32_t line_id = 0;
|
||||||
int32_t shortest_dist;
|
distance_T shortest_dist;
|
||||||
bool found_dist = false;
|
bool found_dist = false;
|
||||||
|
|
||||||
for (uint32_t x = 0; x < image->new_width; x++) {
|
for (uint32_t x = 0; x < image->new_width; x++) {
|
||||||
if (!found_dist || shortest_dist > row[x]) {
|
if (!found_dist || shortest_dist.distance > row[x].distance) {
|
||||||
shortest_dist = row[x];
|
shortest_dist = row[x];
|
||||||
line_id = x;
|
line_id = x;
|
||||||
found_dist = true;
|
found_dist = true;
|
||||||
|
@ -116,19 +119,8 @@ void image_cut_line(image_T* image, uint32_t line_id) {
|
||||||
uint32_t x = line_id;
|
uint32_t x = line_id;
|
||||||
|
|
||||||
for (uint32_t y = image->height-1; y > 0; y--) {
|
for (uint32_t y = image->height-1; y > 0; y--) {
|
||||||
int32_t shortest_dist;
|
distance_T dist = image->dist_buffer[(image->width * y) + x];
|
||||||
int8_t offset;
|
x += dist.direction;
|
||||||
bool found_dist = false;
|
|
||||||
for (int i = (x > 0 ? -1 : 0); i < (x < image->new_width-1 ? 2 : 1); i++) {
|
|
||||||
int32_t dist = image->dist_buffer[(image->width * y) + x + i];
|
|
||||||
|
|
||||||
if (!found_dist || shortest_dist > dist) {
|
|
||||||
shortest_dist = dist;
|
|
||||||
offset = (int8_t)i;
|
|
||||||
found_dist = true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
x += offset;
|
|
||||||
memcpy(&image->buffer[(image->width * y) + x], &image->buffer[(image->width * y) + x + 1], (image->new_width - x) * sizeof(uint32_t));
|
memcpy(&image->buffer[(image->width * y) + x], &image->buffer[(image->width * y) + x + 1], (image->new_width - x) * sizeof(uint32_t));
|
||||||
memcpy(&image->mask_buffer[(image->width * y) + x], &image->mask_buffer[(image->width * y) + x + 1], (image->new_width - x) * sizeof(uint32_t));
|
memcpy(&image->mask_buffer[(image->width * y) + x], &image->mask_buffer[(image->width * y) + x + 1], (image->new_width - x) * sizeof(uint32_t));
|
||||||
gfx_color(0, 0xFF, 0);
|
gfx_color(0, 0xFF, 0);
|
||||||
|
@ -140,55 +132,31 @@ void image_cut_line(image_T* image, uint32_t line_id) {
|
||||||
}
|
}
|
||||||
|
|
||||||
void image_dump(image_T* image) {
|
void image_dump(image_T* image) {
|
||||||
#if DEBUG_BUILD
|
|
||||||
printf("Pixels:\n");
|
|
||||||
#endif
|
|
||||||
for (int y = 0; y < image->new_height; y++) {
|
for (int y = 0; y < image->new_height; y++) {
|
||||||
uint32_t* pixel_row = &image->buffer[y * image->width];
|
uint32_t *pixel_row = &image->buffer[y * image->width];
|
||||||
|
|
||||||
#if DEBUG_BUILD
|
|
||||||
printf(" ");
|
|
||||||
#endif
|
|
||||||
for (int x = 0; x < image->new_width; x++) {
|
for (int x = 0; x < image->new_width; x++) {
|
||||||
#if DEBUG_BUILD
|
gfx_color((uint8_t) (pixel_row[x] & 0xFF),
|
||||||
printf("%x ", pixel_row[x]);
|
(uint8_t) ((pixel_row[x] >> 8) & 0xFF),
|
||||||
#endif
|
(uint8_t) ((pixel_row[x] >> 16) & 0xFF));
|
||||||
gfx_color((uint8_t)(pixel_row[x] & 0xFF),
|
|
||||||
(uint8_t)((pixel_row[x] >> 8) & 0xFF),
|
|
||||||
(uint8_t)((pixel_row[x] >> 16) & 0xFF));
|
|
||||||
gfx_point(x, y);
|
gfx_point(x, y);
|
||||||
}
|
}
|
||||||
|
|
||||||
#if DEBUG_BUILD
|
|
||||||
printf("\n");
|
|
||||||
#endif
|
|
||||||
}
|
}
|
||||||
|
|
||||||
gfx_color(0, 0, 0);
|
gfx_color(0, 0, 0);
|
||||||
for (int y = 0; y < image->new_height*2; y++) {
|
for (int y = 0; y < image->new_height; y++) {
|
||||||
gfx_point(image->new_width, y);
|
gfx_point(image->new_width, y);
|
||||||
}
|
}
|
||||||
|
|
||||||
gfx_flush();
|
gfx_flush();
|
||||||
|
|
||||||
#if DEBUG_BUILD
|
|
||||||
printf("Distances:\n");
|
|
||||||
for (int y = 0; y < image->height; y++) {
|
|
||||||
uint32_t* dist_row = &image->dist_buffer[y * image->width];
|
|
||||||
|
|
||||||
printf(" ");
|
|
||||||
for (int x = 0; x < image->width; x++) {
|
|
||||||
printf("%x ", dist_row[x]);
|
|
||||||
}
|
|
||||||
printf("\n");
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
}
|
}
|
||||||
|
|
||||||
int main() {
|
|
||||||
|
int main(int argc, char* argv[]) {
|
||||||
printf("Line Cutter - Juniorcamp Informatik\n");
|
printf("Line Cutter - Juniorcamp Informatik\n");
|
||||||
|
|
||||||
image_T* image = image_load("../paris.png", "../paris_mask.png");
|
image_T* image = image_load("../bench.png", "../bench_mask.png");
|
||||||
|
|
||||||
gfx_open(800, 600, "Juniorcamp Informatik - Line Cutter");
|
gfx_open(800, 600, "Juniorcamp Informatik - Line Cutter");
|
||||||
image_dump(image);
|
image_dump(image);
|
||||||
|
|
BIN
paris_mask.png
BIN
paris_mask.png
Binary file not shown.
Before Width: | Height: | Size: 7.1 KiB After Width: | Height: | Size: 7.6 KiB |
Loading…
Reference in New Issue