~ruther/CTU-FEE-B0B35APO-Semestral-project

75b7cf9fd2c1d90e2f924d86cd00f4d8f1e7e8f5 — František Boháček 3 years ago c8f0643
feat: add basic image viewer loop
3 files changed, 179 insertions(+), 1 deletions(-)

M .gitignore
A image-viewer/include/image_viewer.h
A image-viewer/src/image_viewer.c
M .gitignore => .gitignore +1 -1
@@ 1,4 1,4 @@
compile-commands.json
compile_commands.json
.cache
ignore
bin/

A image-viewer/include/image_viewer.h => image-viewer/include/image_viewer.h +28 -0
@@ 0,0 1,28 @@
#ifndef __IMAGE_VIEWER_H__
#define __IMAGE_VIEWER_H__

#include <stdbool.h>
#include "image.h"
#include "display_utils.h"
#include "cursor.h"
#include "logger.h"

typedef struct {
  image_t image;
  cursor_t cursor;
  image_region_t region;

  display_t *display;
  bool running;

  logger_t *logger;
} image_viewer_t;

image_viewer_t image_viewer_create(char *filename, display_t *display, logger_t *logger);
void image_viewer_destroy(image_viewer_t *viewer);

void image_viewer_start_loop(image_viewer_t *viewer, void *reg_knobs_base);

void image_viewer_display_image(image_viewer_t *viewer);

#endif // __IMAGE_VIEWER_H__

A image-viewer/src/image_viewer.c => image-viewer/src/image_viewer.c +150 -0
@@ 0,0 1,150 @@
#include "image_viewer.h"
#include "cursor.h"
#include "display_utils.h"
#include "image.h"
#include "input.h"
#include "logger.h"
#include <time.h>
#include <stdlib.h>

#define COMMANDS_NUM 30
#define CURSOR_SHOW_DURATION 3 // seconds

image_viewer_t image_viewer_create(char *filename, display_t *display, logger_t *logger) {
  image_viewer_t viewer = {
    .display = display,
    .image = image_create(filename),
    .cursor = cursor_create(),
    .region = image_region_create(0, 0, 0, 0),
    .logger = logger,
  };

  if (image_load(&viewer.image)) {
    viewer.region = image_region_create(0, 0, viewer.image.width, viewer.image.height);
  }

  return viewer;
}

void image_viewer_destroy(image_viewer_t *viewer) {
  image_destroy(&viewer->image);
}

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);
  cursor_move(&viewer->cursor, &viewer->region, LEFT, amount);
  cursor_show(&viewer->cursor, viewer->display);
  display_render(viewer->display);
}

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);
  cursor_move(&viewer->cursor, &viewer->region, RIGHT, amount);
  cursor_show(&viewer->cursor, viewer->display);
  display_render(viewer->display);
}

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);
  cursor_move(&viewer->cursor, &viewer->region, UP, amount);
  cursor_show(&viewer->cursor, viewer->display);
  display_render(viewer->display);
}

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);
  cursor_move(&viewer->cursor, &viewer->region, DOWN, amount);
  cursor_show(&viewer->cursor, viewer->display);
  display_render(viewer->display);
}

void command_handler_exit(void *data, int amount) {
  image_viewer_t *viewer = (image_viewer_t *)data;
  viewer->running = false;
}

// TODO: implement zoom functions
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);
}

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);
}

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);
}

void image_viewer_register_commands(image_viewer_t *viewer, commands_t *commands) {
  commands_register(commands, IN_KEYBOARD, 'h', &command_handler_move_left,
                    viewer);
  commands_register(commands, IN_KEYBOARD, 'j', &command_handler_move_down,
                    viewer);
  commands_register(commands, IN_KEYBOARD, 'k', &command_handler_move_up,
                    viewer);
  commands_register(commands, IN_KEYBOARD, 'l', &command_handler_move_right,
                    viewer);

  commands_register(commands, IN_KEYBOARD, 'e', &command_handler_exit,
                    viewer);

  commands_register(commands, IN_KEYBOARD, 'z', &command_handler_zoom_in,
                    viewer);
  commands_register(commands, IN_KEYBOARD, 'x', &command_handler_zoom_out,
                    viewer);
  commands_register(commands, IN_KEYBOARD, 'r', &command_handler_zoom_reset,
                    viewer);

  commands_register(commands, IN_ENCODER_ROTATE, 0, &command_handler_move_right,
                    viewer);
  commands_register(commands, IN_ENCODER_ROTATE, 1,
                    &command_handler_move_down, viewer);
  commands_register(commands, IN_ENCODER_ROTATE, 2, &command_handler_zoom_in,
                    viewer);

  commands_register(commands, IN_ENCODER_CLICK, 0, &command_handler_exit,
                    viewer);

  commands_register(commands, IN_ENCODER_CLICK, 2, &command_handler_zoom_reset,
                    viewer);
}

void image_viewer_start_loop(image_viewer_t *viewer, void *reg_knobs_base) {
  command_t command_array[COMMANDS_NUM];
  commands_t commands = commands_create(command_array, COMMANDS_NUM, reg_knobs_base);

  image_viewer_register_commands(viewer, &commands);

  viewer->running = true;
  time_t now = time(NULL);
  while (viewer->running) {
    // Main loop
    commands_check_input(&commands);
    now = time(NULL);

    if (viewer->cursor.shown && difftime(now, viewer->cursor.shown_at) >= CURSOR_SHOW_DURATION) {
      cursor_hide(&viewer->cursor, viewer->display);
      display_render(viewer->display);
    }
  }
}

void image_viewer_display_image(image_viewer_t *viewer) {
  image_write_to_display(&viewer->image, viewer->display, viewer->region);
}

Do not follow this link