Created
March 29, 2023 16:46
-
-
Save jw910731/734765c9a5f1ce15c3fab68c7983ff46 to your computer and use it in GitHub Desktop.
A simple terminal bmp displayer
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
| #include <stdint.h> | |
| #include <sys/ioctl.h> | |
| #include <stdio.h> | |
| #include <unistd.h> | |
| #include <stdbool.h> | |
| #include <string.h> | |
| #include <stdlib.h> | |
| #include <errno.h> | |
| #include <signal.h> | |
| #define ASCII_ESC "\033" | |
| #define CLR_RST ASCII_ESC"[0m" | |
| typedef unsigned char byte; | |
| struct bmpHeader { | |
| char bm[2]; | |
| uint32_t size; | |
| uint32_t reserve; | |
| uint32_t offset; | |
| uint32_t header_size; | |
| int32_t width; | |
| int32_t height; | |
| uint16_t planes; | |
| uint16_t bpp; | |
| uint32_t compression; | |
| uint32_t bitmap_size; | |
| int32_t hres; | |
| int32_t vres; | |
| uint32_t used; | |
| uint32_t important; | |
| } __attribute__((__packed__)); | |
| struct pix_t { | |
| byte b, g, r; | |
| } __attribute__((__packed__)); | |
| struct picture_t { | |
| struct pix_t *blob; | |
| int32_t w, h; | |
| }; | |
| /* | |
| * Read BMP file | |
| * | |
| * @param file is the BMP file object | |
| * @param out is the destination object | |
| * | |
| * @return successful or not | |
| */ | |
| bool read_bmp(struct picture_t *out, FILE *file){ | |
| if(file == NULL){ | |
| fprintf(stderr, "fopen(): %s\n", strerror(errno)); | |
| return false; | |
| } | |
| if(out == NULL) return false; | |
| // read write header | |
| struct bmpHeader header, outHeader; | |
| fread(&header, 54, 1, file); | |
| memcpy(&outHeader, &header, sizeof(header)); | |
| // calc info | |
| *out = (struct picture_t){.w = abs(header.width), | |
| .h = abs(header.height), | |
| .blob = | |
| calloc(abs(header.width) * abs(header.height), | |
| sizeof(struct pix_t))}; | |
| int32_t ipad_siz = (((24 * out->w + 31) / 32) * 4) - (3 * out->w); | |
| // read data by row | |
| for (int32_t i = 0; i < out->h; ++i) { | |
| fread(out->blob + (out->w * i), out->w, sizeof(struct pix_t), file); | |
| // skip padding bytes | |
| fseek(file, ipad_siz, SEEK_CUR); | |
| } | |
| fclose(file); | |
| return true; | |
| } | |
| // global maintained terminal size object | |
| static struct winsize term_size; | |
| static inline void update_terminal_size(int sig) { | |
| ioctl(STDOUT_FILENO, TIOCGWINSZ, &term_size); | |
| term_size.ws_row -= 2; | |
| } | |
| int main(int argc, const char **argv) { | |
| if(argc < 2) { | |
| fprintf(stderr, "No enough argument.\n"); | |
| return 1; | |
| } | |
| struct picture_t picture; | |
| if(!read_bmp(&picture, fopen(argv[1], "rb"))){ | |
| return 1; | |
| } | |
| update_terminal_size(SIGWINCH); | |
| static const char clear_seq[] = {0x1b, 0x5b, 0x48, 0x1b, 0x5b, 0x32, 0x4a, 0x00}; | |
| fputs(clear_seq, stdout); | |
| // display | |
| for(int32_t i = term_size.ws_row ; i >= 0 ; --i){ | |
| for(int32_t j = 0 ; j < term_size.ws_col ; ++j){ | |
| int32_t x = (int32_t)(j*((double)(picture.w-1)/term_size.ws_col)+0.5), | |
| y = (int32_t)(i*((double)(picture.h-1)/term_size.ws_row)+0.5); | |
| struct pix_t *pix = picture.blob + (y*picture.w + x); | |
| //printf("(%d, %d) -> (%hhu, %hhu, %hhu)\n", x, y, pix->r, pix->g, pix->b); | |
| printf(ASCII_ESC"[38;2;%hhu;%hhu;%hhum█"CLR_RST, pix->r, pix->g, pix->b); | |
| } | |
| } | |
| free(picture.blob); | |
| return 0; | |
| } |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Nin is too Dian