Created
May 3, 2024 14:47
-
-
Save angelcaru/3abb9829e982d513a7d3dfdf92c9e14b to your computer and use it in GitHub Desktop.
Simple ANSI terminal image viewer in C
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// NOTE: you will need stb_image in order to compile this | |
// Currently only works on POSIX-compliant systems because of the use of ioctl() | |
#define STB_IMAGE_IMPLEMENTATION | |
#include "stb_image.h" | |
#include <sys/ioctl.h> | |
void usage(const char *program_name) { | |
printf("Usage: %s <filename>\n", program_name); | |
} | |
typedef union { | |
uint32_t rgba; | |
struct { | |
uint8_t r, g, b, a; | |
}; | |
} Color; | |
void set_bg(Color c) { | |
printf("\x1b[48;2;%d;%d;%dm", c.r, c.g, c.b); | |
} | |
void reset_term(void) { | |
printf("\x1b[0m"); | |
} | |
void get_term_size(int *w, int *h) { | |
struct winsize ws; | |
ioctl(fileno(stderr), TIOCGWINSZ, &ws); | |
*w = ws.ws_col; | |
*h = ws.ws_row; | |
} | |
#define ASSUMED_BG ((Color) { .r = 24, .g = 24, .b = 24, .a = 255 }) // Used for alpha | |
float lerp(float a, float b, float t) { | |
return a + (b - a) * t; | |
} | |
Color color_lerp(Color a, Color b, float t) { | |
return (Color) { | |
.r = lerp(a.r, b.r, t), | |
.g = lerp(a.g, b.g, t), | |
.b = lerp(a.b, b.b, t), | |
.a = lerp(a.a, b.a, t), | |
}; | |
} | |
char *shift_args(int *argc, char ***argv) { | |
--*argc; | |
char *ret = **argv; | |
++*argv; | |
return ret; | |
} | |
int main(int argc, char **argv) { | |
const char *program_name = shift_args(&argc, &argv); | |
if (argc == 0) { | |
usage(program_name); | |
fprintf(stderr, "ERROR: no filename provided\n"); | |
return 1; | |
} | |
char *path = shift_args(&argc, &argv); | |
int width, height; | |
unsigned char *data_c = stbi_load(path, &width, &height, NULL, 4); | |
if (data_c == NULL) { | |
fprintf(stderr, "Could not load image %s: %s", path, stbi_failure_reason()); | |
return 1; | |
} | |
Color *data = (Color *)data_c; | |
int termwidth, termheight; | |
get_term_size(&termwidth, &termheight); | |
float ystep = height / (termheight * 0.8); | |
float xstep = ystep / 2; | |
for (float y = 0; y < height; y += ystep) { | |
for (float x = 0; x < width; x += xstep) { | |
Color c = data[(int)y * width + (int)x]; | |
if (c.a < 255) { | |
c = color_lerp(ASSUMED_BG, c, c.a / 255.0f); | |
} | |
set_bg(c); | |
printf(" "); | |
} | |
reset_term(); | |
printf("\n"); | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment