130 if (!rgba_data || src_width <= 0 || src_height <= 0) {
135 int dst_width = GET_OPTION(width);
136 int dst_height = GET_OPTION(height);
137 color_filter_t filter = (color_filter_t)GET_OPTION(color_filter);
138 terminal_color_mode_t color_mode = (terminal_color_mode_t)GET_OPTION(color_mode);
139 palette_type_t palette_type = (palette_type_t)GET_OPTION(palette_type);
141 bool stretch =
false;
144 terminal_capabilities_t caps = {0};
145 caps.color_level = color_mode;
146 caps.capabilities = 0;
147 caps.color_count = (color_mode == TERM_COLOR_NONE) ? 0
148 : (color_mode == TERM_COLOR_16) ? 16
149 : (color_mode == TERM_COLOR_256) ? 256
151 caps.utf8_support =
true;
152 caps.detection_reliable =
true;
153 caps.render_mode = (render_mode_t)GET_OPTION(render_mode);
154 caps.wants_background =
false;
155 caps.palette_type = palette_type;
156 caps.desired_fps = 60;
157 caps.color_filter = filter;
160 rgb_pixel_t *rgb_pixels = SAFE_MALLOC(src_width * src_height *
sizeof(rgb_pixel_t), rgb_pixel_t *);
165 bool flip = GET_OPTION(flip_x);
166 for (
int y = 0; y < src_height; y++) {
167 for (
int x = 0; x < src_width; x++) {
168 int src_x = flip ? (src_width - 1 - x) : x;
169 int src_idx = (y * src_width + src_x) * 4;
170 int dst_idx = y * src_width + x;
172 rgb_pixels[dst_idx].r = rgba_data[src_idx + 0];
173 rgb_pixels[dst_idx].g = rgba_data[src_idx + 1];
174 rgb_pixels[dst_idx].b = rgba_data[src_idx + 2];
180 if (filter != COLOR_FILTER_NONE && filter != COLOR_FILTER_RAINBOW) {
182 uint8_t *rgb24 = (uint8_t *)rgb_pixels;
183 int stride = src_width * 3;
184 float time_seconds = (float)(emscripten_get_now() / 1000.0);
189 image_t img = {.w = src_width, .h = src_height, .pixels = rgb_pixels, .alloc_method = IMAGE_ALLOC_SIMD};
192 const char *palette_chars;
193 switch (palette_type) {
195 palette_chars = PALETTE_CHARS_BLOCKS;
197 case PALETTE_DIGITAL:
198 palette_chars = PALETTE_CHARS_DIGITAL;
200 case PALETTE_MINIMAL:
201 palette_chars = PALETTE_CHARS_MINIMAL;
204 palette_chars = PALETTE_CHARS_COOL;
208 palette_chars = GET_OPTION(palette_custom);
209 if (!palette_chars || palette_chars[0] ==
'\0') {
210 palette_chars = PALETTE_CHARS_STANDARD;
213 case PALETTE_STANDARD:
215 palette_chars = PALETTE_CHARS_STANDARD;
224 SAFE_FREE(rgb_pixels);
227 log_error(
"ascii_convert_with_capabilities returned NULL");
233 if (filter == COLOR_FILTER_RAINBOW) {
234 float time_seconds = (float)(emscripten_get_now() / 1000.0);
236 if (rainbow_output) {
237 SAFE_FREE(ascii_output);
238 ascii_output = rainbow_output;
243 bool matrix_rain = GET_OPTION(matrix_rain);
246 if (!g_digital_rain || g_digital_rain->num_columns != dst_width || g_digital_rain->num_rows != dst_height) {
247 if (g_digital_rain) {
250 if (g_last_rain_output) {
251 SAFE_FREE(g_last_rain_output);
252 g_last_rain_output = NULL;
255 if (!g_digital_rain) {
256 log_error(
"Failed to initialize digital rain effect");
259 g_last_rain_update_time = emscripten_get_now();
266 double current_time = emscripten_get_now();
267 double elapsed_ms = current_time - g_last_rain_update_time;
271 float delta_time = (float)(elapsed_ms / 1000.0);
272 g_last_rain_update_time = current_time;
278 if (g_last_rain_output) {
279 SAFE_FREE(g_last_rain_output);
282 g_last_rain_output = strdup(rain_output);
284 SAFE_FREE(ascii_output);
285 ascii_output = rain_output;
287 }
else if (g_last_rain_output) {
289 SAFE_FREE(ascii_output);
290 ascii_output = strdup(g_last_rain_output);
294 if (g_digital_rain) {
296 g_digital_rain = NULL;
298 if (g_last_rain_output) {
299 SAFE_FREE(g_last_rain_output);
300 g_last_rain_output = NULL;
302 g_last_rain_update_time = 0.0;