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

ref: c2d2df67e9eab17c34d09ebf1449f0d1bad7f84f CTU-FEE-B0B35APO-Semestral-project/image-viewer/src/display_utils.c -rw-r--r-- 3.2 KiB
c2d2df67 — František Boháček refactor: handle correctly get and set pixel out of bounds 3 years ago
                                                                                
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
#include "display_utils.h"
#include "mzapo_parlcd.h"
#include <stdlib.h>

#ifdef COMPUTER
#include "xwin_sdl.h"
#endif

const display_pixel_t BLACK_PIXEL = {.bits = 0};
const display_pixel_t WHITE_PIXEL = {.bits = 0xFFFF};

const raw_pixel_t DISPLAY_PIXEL_MAX = {.red = (uint16_t)DISPLAY_MAX_RED,
                                       .green = (uint16_t)DISPLAY_MAX_GREEN,
                                       .blue = (uint16_t)DISPLAY_MAX_BLUE};

static void display_pixel_to_rgb(display_pixel_t pixel, uint8_t *target) {
  *(target++) = ((float)pixel.fields.r / DISPLAY_MAX_RED) * 255;
  *(target++) = ((float)pixel.fields.g / DISPLAY_MAX_GREEN) * 255;
  *(target++) = ((float)pixel.fields.b / DISPLAY_MAX_BLUE) * 255;
}

display_pixel_t raw_pixel_onebit_convert_to_display(raw_pixel_onebit_t pixel,
                                                    raw_pixel_onebit_t max) {
  display_pixel_t new = {
      .fields = {
          .r = ((float)pixel.red / (float)max.red) * DISPLAY_MAX_RED,
          .g = ((float)pixel.green / (float)max.green) * DISPLAY_MAX_GREEN,
          .b = ((float)pixel.blue / (float)max.blue) * DISPLAY_MAX_BLUE,
      }};

  return new;
}

display_pixel_t raw_pixel_convert_to_display(raw_pixel_t pixel,
                                             raw_pixel_t max) {
  display_pixel_t new = {
      .fields = {
          .r = ((float)pixel.red / (float)max.red) * DISPLAY_MAX_RED,
          .g = ((float)pixel.green / (float)max.green) * DISPLAY_MAX_GREEN,
          .b = ((float)pixel.blue / (float)max.blue) * DISPLAY_MAX_BLUE,
      }
  };

  return new;
}

display_t display_init(display_data_t data) {
  display_t display = {
    .data = data
  };

  if (data.base_address != NULL) {
    parlcd_hx8357_init(data.base_address);
    display_clear(&display, true);
  }

  #ifdef COMPUTER
  xwin_init(DISPLAY_WIDTH, DISPLAY_HEIGHT);
  #endif

  return display;
}
void display_deinit(display_t *display) {
#ifdef COMPUTER
  xwin_close();
#else
  display_clear(display, true);
#endif
}

void display_render(display_t *display) {
  #ifdef COMPUTER
  uint8_t data[DISPLAY_WIDTH * DISPLAY_HEIGHT * 3];
  for (int i = 0; i < DISPLAY_WIDTH * DISPLAY_HEIGHT; i++) {
    display_pixel_to_rgb(display->pixels[i], data + i * 3);
  }

  xwin_redraw(DISPLAY_WIDTH, DISPLAY_HEIGHT, data);
#else
  if (display->data.base_address == NULL) {
    return;
  }

  parlcd_write_cmd(display->data.base_address, PARLCD_CMD_FRAMEBUFFER);
  int count = DISPLAY_HEIGHT * DISPLAY_WIDTH;
  for (int i = 0; i < count; i++) {
    parlcd_write_data(display->data.base_address, display->pixels[i].bits);
  }
  #endif
}

void display_clear(display_t *display, bool render) {

  int count = DISPLAY_HEIGHT * DISPLAY_WIDTH;
  for (int i = 0; i < count; i++) {
    display->pixels[i] = BLACK_PIXEL;
  }

  if (render) {
    display_render(display);
  }
}

display_pixel_t display_get_pixel(display_t *display, uint16_t x, uint16_t y) {
  if (y >= DISPLAY_HEIGHT || x >= DISPLAY_WIDTH) {
    return BLACK_PIXEL;
  }

  return display->pixels[y * DISPLAY_WIDTH + x];
}

void display_set_pixel(display_t *display, uint16_t x, uint16_t y,
                       display_pixel_t pixel) {
  if (y >= DISPLAY_HEIGHT || x >= DISPLAY_WIDTH) {
    return;
  }

  display->pixels[y * DISPLAY_WIDTH + x] = pixel;
}
Do not follow this link