💾 Archived View for gemini.rmf-dev.com › repo › Vaati › Vgmi › files › 753ea1f1a8f9bfdd30f5d7cae57b1… captured on 2023-12-28 at 15:43:15. Gemini links have been rewritten to link to archived content

View Raw

More Information

-=-=-=-=-=-=-

Go Back

0 /*

1 * ISC License

2 * Copyright (c) 2023 RMF <rawmonk@firemail.cc>

3 */

4 #include <stdlib.h>

5 #include "image.h"

6 #ifdef ENABLE_IMAGE

7 #include <stdio.h>

8 #include <stdint.h>

9 #include <unistd.h>

10 #include <string.h>

11 #include <poll.h>

12 #include "sandbox.h"

13 #include "termbox.h"

14 #include "error.h"

15 #include "proc.h"

16 #include "macro.h"

17 #include "config.h"

18

19 int image_process = 0;

20

21 static int _write(int fd, char *data, int length) {

22 int i;

23 for (i = 0; i < length;) {

24 int bytes = write(fd, &data[i], length - i);

25 if (bytes < 1) return -1;

26 i += bytes;

27 }

28 return 0;

29 }

30

31 static int _read(int fd, void *ptr, int length) {

32 int i;

33 char *data = ptr;

34 struct pollfd pfd;

35 pfd.fd = fd;

36 pfd.events = POLLIN;

37 for (i = 0; i < length;) {

38 int bytes;

39 if (!poll(&pfd, 1, 3000)) return -1;

40 bytes = read(fd, &data[i], length);

41 if (bytes < 1) return -1;

42 i += bytes;

43 }

44 return 0;

45 }

46

47 static int __read(int fd, void *ptr, int length) {

48 int i;

49 char *data = ptr;

50 for (i = 0; i < length;) {

51 int bytes;

52 bytes = read(fd, &data[i], length);

53 if (bytes < 1) return -1;

54 i += bytes;

55 }

56 return 0;

57 }

58

59 static int empty_pipe(int fd) {

60 struct pollfd pfd;

61 pfd.fd = fd;

62 pfd.events = POLLIN;

63 while (poll(&pfd, 1, 0)) {

64 uint8_t byte;

65 if (read(fd, &byte, 1) != 1) return -1;

66 }

67 return 0;

68 }

69

70 void image_parser(int in, int out) {

71

72 char *data;

73 uint8_t byte;

74 #ifdef STATIC_ALLOC

75 size_t length;

76

77 data = malloc(config.imageParserScratchPad);

78 if (!data) return;

79 memset(data, 0, config.imageParserScratchPad);

80 image_memory_set(data, config.imageParserScratchPad);

81

82 length = config.imageParserScratchPad / 2;

83 data = malloc(length);

84 if (!data) return;

85 memset(data, 0, length);

86 #else

87 data = NULL;

88 #endif

89

90 sandbox_set_name("vgmi [image]");

91 sandbox_isolate();

92

93 byte = 0;

94 write(out, &byte, 1);

95

96 while (1) {

97

98 int x, y, size;

99 void *img;

100

101 img = NULL;

102 size = y = x = 0;

103

104 if (read(in, P(size)) != sizeof(size)) break;

105 #ifdef STATIC_ALLOC

106 if ((unsigned)size > length) goto fail;

107 #else

108 data = malloc(size);

109 if (!data) goto fail;

110 #endif

111 if (!size) goto fail;

112 write(out, P(size));

113 if (__read(in, data, size)) goto fail;

114 img = image_load(data, size, &x, &y);

115 if (!img) goto fail;

116 #ifndef STATIC_ALLOC

117 free(data);

118 #endif

119 write(out, P(x));

120 write(out, P(y));

121 if (_write(out, img, x * y * 3)) break;

122 #ifndef STATIC_ALLOC

123 free(img);

124 #endif

125 continue;

126 fail:

127 size = -1;

128 write(out, P(size));

129 free(data);

130 }

131 }

132

133 #define OK(X) if (X) return NULL

134 int image_fd_out = -1;

135 int image_fd_in = -1;

136 void *image_parse(void *data, int len, int *x, int *y) {

137 int _x, _y, size;

138 void *img;

139 if (image_fd_out == -1 || image_fd_in == -1) return NULL;

140 empty_pipe(image_fd_in);

141 write(image_fd_out, P(len));

142 OK(_read(image_fd_in, P(size)));

143 OK(size != len);

144 OK(_write(image_fd_out, data, len));

145 OK(_read(image_fd_in, P(_x)));

146 OK(_x == -1);

147 OK(_read(image_fd_in, P(_y)));

148 size = _x * _y * 3;

149 OK(size < 1 || size > config.imageParserScratchPad);

150 img = malloc(size);

151 if (!img || _read(image_fd_in, img, size)) {

152 free(img);

153 return NULL;

154 }

155 *x = _x;

156 *y = _y;

157 return img;

158 }

159

160 int image_init() {

161 int ret;

162 if (!config.enableImage) return 0;

163 ret = proc_fork("--image", &image_fd_in, &image_fd_out);

164 if (ret) return ret;

165 image_process = 1;

166 return 0;

167 }

168

169 static int color_abs(int c, int x, int i) {

170 return abs(c -= i > 215 ? i * 10 - 2152:x * 40 + !!x * 55);

171 }

172

173 static int color(uint8_t r, uint8_t g, uint8_t b) {

174 int m = 0, t = 0, i = 240, l = 240;

175 while (i--) {

176 t = color_abs(r, i / 36, i) + color_abs(g, i / 6 % 6, i) +

177 color_abs(b, i % 6, i);

178 if (t < l) {

179 l = t;

180 m = i;

181 }

182 }

183 i = m + 16;

184 return i;

185 }

186

187 int average_pixel(uint8_t* data, int x, int y, int w, int h, float ratio) {

188 int pixels = 0;

189 int r = 0, g = 0, b = 0, i, j;

190 float precision = 2;

191 float rp = ratio / precision;

192 for (i = x - rp; i < x + rp; i++) {

193 if (i >= w || i < 0) continue;

194 for (j = y - rp; j < y + rp; j++) {

195 if (j >= h || j < 0) continue;

196 r += data[(i + j * w) * 3];

197 g += data[(i + j * w) * 3 + 1];

198 b += data[(i + j * w) * 3 + 2];

199 pixels++;

200 }

201 }

202 if (pixels == 0) return TB_DEFAULT;

203 return color(r / pixels, g / pixels, b / pixels);

204 }

205

206 int image_display(unsigned char* data, int w, int h, int offsety) {

207 int _x = 0, _y = 0;

208 double x, y;

209 double w_ratio = (double)w/(tb_width());

210 double h_ratio = (double)h/((tb_height() - offsety - 2) * 2);

211

212 if (w_ratio < h_ratio)

213 w_ratio = h_ratio;

214 else

215 h_ratio = w_ratio;

216

217 for (x = 0; x < (double)w; x += w_ratio) {

218 for (y = 0; y < (double)h; y += h_ratio) {

219 int fg = average_pixel(data, x, y + 1, w, h, h_ratio);

220 int bg = average_pixel(data, x, y, w, h, h_ratio);

221 tb_set_cell(_x, _y + offsety, 0x2584, fg, bg);

222 y += h_ratio;

223 _y++;

224 }

225 _y = 0;

226 _x++;

227 }

228 return 0;

229 }

230 #else

231 typedef int hide_warning;

232 #endif

233