Skip to content

Instantly share code, notes, and snippets.

@angelcaru
Created May 3, 2024 14:47
Show Gist options
  • Save angelcaru/3abb9829e982d513a7d3dfdf92c9e14b to your computer and use it in GitHub Desktop.
Save angelcaru/3abb9829e982d513a7d3dfdf92c9e14b to your computer and use it in GitHub Desktop.
Simple ANSI terminal image viewer in C
// 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