#include "image_viewer_handlers.h" #include "cursor.h" #include "keyboard_const.h" #include "rotation_const.h" #define MAX_ZOOM 10 #define MIN_ZOOM 0.02 void image_viewer_display_image(image_viewer_t *viewer) { cursor_hide(&viewer->cursor, &viewer->image, viewer->scale, viewer->display); viewer->scale = image_write_to_display(&viewer->image, viewer->display, viewer->scale); display_render(viewer->display); } static void image_viewer_handle_moved_cursor(image_viewer_t *viewer, bool move_cursor, direction_t direction, int amount, int32_t x, int32_t y) { if (x < 0) { x = 0; } if (y < 0) { y = 0; } viewer->scale.x = x; viewer->scale.y = y; if (move_cursor) { cursor_move(&viewer->cursor, image_get_zoom_region(&viewer->image, viewer->scale), direction, amount / viewer->scale.scale); } image_viewer_display_image(viewer); cursor_show(&viewer->cursor, &viewer->image, viewer->scale, viewer->display); display_render(viewer->display); ledstrip_turn_on( &viewer->ledstrip, ((double)viewer->cursor.x / viewer->image.width) * LED_STRIP_COUNT, 1); } static void command_handler_move_cursor(void *data, direction_t direction, int amount) { image_viewer_t *viewer = (image_viewer_t *)data; cursor_hide(&viewer->cursor, &viewer->image, viewer->scale, viewer->display); int32_t x = viewer->scale.x, y = viewer->scale.y; bool move_cursor = false; switch (viewer->mode) { case MOD_CURSOR: if (!cursor_move(&viewer->cursor, image_get_zoom_region(&viewer->image, viewer->scale), direction, amount / viewer->scale.scale)) { direction_move_xy(direction, &x, &y, amount / viewer->scale.scale); move_cursor = true; } break; case MOD_IMAGE: logger_debug(viewer->logger, __FILE__, __FUNCTION__, __LINE__, "Moving image"); direction_move_xy(direction, &x, &y, amount / viewer->scale.scale); move_cursor = true; break; default: break; } image_viewer_handle_moved_cursor(viewer, move_cursor, direction, amount, x, y); } static void command_handler_move_left(void *data, int amount) { image_viewer_t *viewer = (image_viewer_t*)data; logger_debug(viewer->logger, __FILE__, __FUNCTION__, __LINE__, "Moving cursor to left by %d", amount); command_handler_move_cursor(data, LEFT, amount); } static void command_handler_move_right(void *data, int amount) { image_viewer_t *viewer = (image_viewer_t *)data; logger_debug(viewer->logger, __FILE__, __FUNCTION__, __LINE__, "Moving cursor to right by %d", amount); command_handler_move_cursor(data, RIGHT, amount); } static void command_handler_move_up(void *data, int amount) { image_viewer_t *viewer = (image_viewer_t *)data; logger_debug(viewer->logger, __FILE__, __FUNCTION__, __LINE__, "Moving cursor up by %d", amount); command_handler_move_cursor(data, UP, amount); } static void command_handler_move_down(void *data, int amount) { image_viewer_t *viewer = (image_viewer_t *)data; logger_debug(viewer->logger, __FILE__, __FUNCTION__, __LINE__, "Moving cursor down by %d", amount); command_handler_move_cursor(data, DOWN, amount); } static void command_handler_exit(void *data, int amount) { image_viewer_t *viewer = (image_viewer_t *)data; viewer->running = false; } static image_zoom_t zoom_get_new(image_viewer_t *viewer, int amount) { double zoom = viewer->scale.scale; double new_zoom = zoom * (1 + amount * 0.05); if (new_zoom > MAX_ZOOM) { logger_warn(viewer->logger, __FILE__, __FUNCTION__, __LINE__, "Cannot zoom more than %f", MAX_ZOOM); new_zoom = MAX_ZOOM; } if (new_zoom < MIN_ZOOM) { logger_warn(viewer->logger, __FILE__, __FUNCTION__, __LINE__, "Cannot zoom less than %f", MIN_ZOOM); new_zoom = MIN_ZOOM; } image_zoom_t tmp = { .scale = new_zoom, .x = viewer->scale.x, .y = viewer->scale.y, }; return tmp; } static void zoom(image_viewer_t *viewer, int amount) { double zoom = viewer->scale.scale; image_region_t current_region = image_get_zoom_region(&viewer->image, viewer->scale); image_zoom_t tmp = zoom_get_new(viewer, amount); image_region_t new_region = image_get_zoom_region(&viewer->image, tmp); uint16_t scaled_w = (uint16_t)(zoom * viewer->image.width), scaled_h = (uint16_t)(zoom * viewer->image.height); int32_t beg_x = ((double)DISPLAY_WIDTH - (double)(scaled_w)) / 2; int32_t beg_y = ((double)DISPLAY_HEIGHT - (double)(scaled_h)) / 2; if (beg_x < 0) { beg_x = 0; } if (beg_y < 0) { beg_y = 0; } if (scaled_w > DISPLAY_WIDTH) { scaled_w = DISPLAY_WIDTH; } if (scaled_h > DISPLAY_HEIGHT) { scaled_h = DISPLAY_HEIGHT; } int32_t diff_w = current_region.width - new_region.width; int32_t diff_h = current_region.height - new_region.height; double side_percentage_x = (double)(viewer->cursor.x - current_region.x) / current_region.width; double side_percentage_y = (double)(viewer->cursor.y - current_region.y) / current_region.height; tmp.x += side_percentage_x * diff_w; tmp.y += side_percentage_y * diff_h; viewer->scale = tmp; image_viewer_display_image(viewer); cursor_show(&viewer->cursor, &viewer->image, viewer->scale, viewer->display); } static void command_handler_zoom_in(void *data, int amount) { // hide cursor, zoom, show cursor image_viewer_t *viewer = (image_viewer_t *)data; logger_debug(viewer->logger, __FILE__, __FUNCTION__, __LINE__, "Zooming in by %d", amount); zoom(viewer, amount); } static void command_handler_zoom_out(void *data, int amount) { image_viewer_t *viewer = (image_viewer_t *)data; logger_debug(viewer->logger, __FILE__, __FUNCTION__, __LINE__, "Zooming out by %d", amount); zoom(viewer, -amount); } static void command_handler_zoom_reset(void *data, int amount) { image_viewer_t *viewer = (image_viewer_t *)data; logger_debug(viewer->logger, __FILE__, __FUNCTION__, __LINE__, "Zoom reset by %d", amount); viewer->scale = image_get_initial_zoom(&viewer->image); image_viewer_display_image(viewer); cursor_center(&viewer->cursor, viewer->image_region); cursor_show(&viewer->cursor, &viewer->image, viewer->scale, viewer->display); } static void command_handler_change_mode(void *data, int amount) { if (!amount) { return; } image_viewer_t *viewer = (image_viewer_t *)data; logger_debug(viewer->logger, __FILE__, __FUNCTION__, __LINE__, "Changing mode"); uint8_t mode = viewer->mode; mode++; if (mode >= MOD_COUNT) { mode %= MOD_COUNT; } if (mode == MOD_IMAGE) { rgb_led_set_green(&viewer->rgb_leds, LED_LEFT); rgb_led_set_green(&viewer->rgb_leds, LED_RIGHT); } else { rgb_led_clear(&viewer->rgb_leds, LED_LEFT); rgb_led_clear(&viewer->rgb_leds, LED_RIGHT); } viewer->mode = mode; } void image_viewer_register_commands(image_viewer_t *viewer, commands_t *commands) { commands_register(commands, IN_KEYBOARD, KEYBOARD_LEFT, &command_handler_move_left, viewer); commands_register(commands, IN_KEYBOARD, KEYBOARD_DOWN, &command_handler_move_down, viewer); commands_register(commands, IN_KEYBOARD, KEYBOARD_UP, &command_handler_move_up, viewer); commands_register(commands, IN_KEYBOARD, KEYBOARD_RIGHT, &command_handler_move_right, viewer); commands_register(commands, IN_KEYBOARD, 'e', &command_handler_exit, viewer); commands_register(commands, IN_KEYBOARD, KEYBOARD_ZOOM_IN, &command_handler_zoom_in, viewer); commands_register(commands, IN_KEYBOARD, KEYBOARD_ZOOM_OUT, &command_handler_zoom_out, viewer); commands_register(commands, IN_KEYBOARD, 'r', &command_handler_zoom_reset, viewer); commands_register(commands, IN_KEYBOARD, 'm', &command_handler_change_mode, viewer); commands_register(commands, IN_ENCODER_ROTATE, ROTATION_ENCODER_HORIZONTAL, &command_handler_move_right, viewer); commands_register(commands, IN_ENCODER_ROTATE, ROTATION_ENCODER_VERTICAL, &command_handler_move_down, viewer); commands_register(commands, IN_ENCODER_ROTATE, ROTATION_ENCODER_ZOOM, &command_handler_zoom_in, viewer); commands_register(commands, IN_ENCODER_CLICK, 0, &command_handler_exit, viewer); commands_register(commands, IN_ENCODER_CLICK, 1, &command_handler_change_mode, viewer); commands_register(commands, IN_ENCODER_CLICK, 2, &command_handler_zoom_reset, viewer); }