From f15b53eea4b7054826f79836e207751e86ba1cec Mon Sep 17 00:00:00 2001 From: Jonas Gunz Date: Sat, 4 May 2019 00:57:44 +0200 Subject: Reorganised folder structure --- Makefile | 10 +-- bitmap.c | 160 -------------------------------------- bitmap.h | 70 ----------------- character.c | 10 --- character.h | 12 --- color.c | 74 ------------------ color.h | 33 -------- m.c | 22 ------ m.h | 14 ---- main.c | 235 -------------------------------------------------------- src/bitmap.c | 160 ++++++++++++++++++++++++++++++++++++++ src/bitmap.h | 70 +++++++++++++++++ src/character.c | 10 +++ src/character.h | 12 +++ src/color.c | 74 ++++++++++++++++++ src/color.h | 33 ++++++++ src/m.c | 22 ++++++ src/m.h | 14 ++++ src/main.c | 235 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 19 files changed, 634 insertions(+), 636 deletions(-) delete mode 100644 bitmap.c delete mode 100644 bitmap.h delete mode 100644 character.c delete mode 100644 character.h delete mode 100644 color.c delete mode 100644 color.h delete mode 100644 m.c delete mode 100644 m.h delete mode 100644 main.c create mode 100644 src/bitmap.c create mode 100644 src/bitmap.h create mode 100644 src/character.c create mode 100644 src/character.h create mode 100644 src/color.c create mode 100644 src/color.h create mode 100644 src/m.c create mode 100644 src/m.h create mode 100644 src/main.c diff --git a/Makefile b/Makefile index bbecb30..5ef4629 100644 --- a/Makefile +++ b/Makefile @@ -1,11 +1,12 @@ CC = /usr/bin/gcc CFLAGS = -Wall LDFLAGS = -lm +SOURCEDIR = src OUTPUT = bitmap BUILDDIR = build FILE = 022.bmp -SRCS = $(wildcard *.c) +SRCS = $(wildcard $(SOURCEDIR)/*.c) OBJ = $(SRCS:.c=.o) build: $(OBJ) @@ -19,11 +20,8 @@ gdb: debug gdb $(BUILDDIR)/$(OUTPUT) %.o: %.c - @echo - @echo Building $< - @echo ============== - @echo - $(CC) $(CFLAGS) -c $< + @echo [ CC ] $< + @$(CC) $(CFLAGS) -c $< -o $@ all: clean build diff --git a/bitmap.c b/bitmap.c deleted file mode 100644 index bb88b46..0000000 --- a/bitmap.c +++ /dev/null @@ -1,160 +0,0 @@ -#include "bitmap.h" - -uint32_t bitmap_flip_byte(unsigned char* _v, int _c) -{ - uint32_t ret = 0; - uint32_t counter = (_c-1) * 8; - - for(int i = 0; i < _c; i++) - { - ret |= (uint32_t)(_v[i] << (counter)); - counter -= 8; - } - - return ret; -}//flip - -struct bitmap_pixel_data bitmap_read(char *_file) -{ - struct bitmap_pixel_data ret; - struct bitmap_file_header header; - - ret.R = ret.G = ret.B = NULL; - ret.error = 1; - - FILE *bitmap = fopen(_file,"rb"); - - if(!bitmap) - return ret; - - header = bitmap_read_file_header(bitmap); - - if(header.error) - return ret; - - if(header.biBitCount != 24) - return ret; - - if(header.biCompression != 0) - return ret; - - ret = bitmap_read_pixel_data(bitmap, header); - - - free(header.tables); - fclose(bitmap); - - ret.error = 0; - return ret; -} - -struct bitmap_file_header bitmap_read_file_header(FILE *_file) -{ - struct bitmap_file_header ret; - unsigned char fileheader[_HEADER_SIZE]; - uint32_t read_counter = 0; - - ret.error = 1; - - size_t tt = fread((void*)&fileheader, sizeof(char), _HEADER_SIZE, _file); - read_counter += _HEADER_SIZE; - - if(!tt) - return ret; - - //Copy file header - ret.bfType = (uint16_t) bitmap_flip_byte(&fileheader[BF_TYPE], sizeof(ret.bfType)); - - if(ret.bfType != (uint16_t)IDENTIFIER) - return ret; - - ret.bfSize = (uint32_t) bitmap_flip_byte(&fileheader[BF_SIZE], sizeof(ret.bfSize)); - ret.bfOffBits = *(uint32_t*) &fileheader[BF_OFF_BITS]; - ret.biSize = *(uint32_t*) &fileheader[BI_SIZE]; - ret.biWidth = *(int32_t*) &fileheader[BI_WIDTH]; - ret.biHeight = *(int32_t*) &fileheader[BI_HEIGHT]; - ret.biBitCount = *(uint16_t*) &fileheader[BI_BIT_COUNT]; - ret.biCompression = (uint32_t) bitmap_flip_byte(&fileheader[BI_COMPRESSION], sizeof(ret.biCompression)); - ret.biSizeImage = *(uint32_t*) &fileheader[BI_SIZE_IMAGE]; - ret.biClrUsed = (uint32_t) bitmap_flip_byte(&fileheader[BI_CLR_USED], sizeof(ret.biClrUsed)); - ret.biClrImportant = (uint32_t) bitmap_flip_byte(&fileheader[BI_CLR_IMPORTANT], sizeof(ret.biClrImportant)); - - - //Read to start of Pixel block - //This block contains Colormasks and Colortables. - ret.tablesc = ret.bfOffBits - read_counter; - ret.tables = malloc(sizeof(char)* ret.tablesc); - fread(ret.tables, sizeof(char), ret.tablesc, _file); - ////////// - - ret.error = 0; - return ret; -} - -struct bitmap_pixel_data bitmap_read_pixel_data(FILE *_file, struct bitmap_file_header _header) -{ - uint32_t **bitmap_buff; - - struct bitmap_pixel_data ret; - - uint32_t row_size = _header.biWidth * 3; - while(row_size%4) - row_size++; - - ret.x = _header.biWidth; - ret.y = _header.biHeight < 0 ? -_header.biHeight: _header.biHeight; - - //If biHeight > 0 Data starts with last row!! - - //Allocate 2D array - //!! - //bitmap_buff indeces are flipped!! [y][x]!!!!! - bitmap_buff = malloc(sizeof(*bitmap_buff) * _header.biHeight); - for(int i = 0; i < ret.y; i++) - { - bitmap_buff[i] = malloc(sizeof(*bitmap_buff[i]) * _header.biWidth); - } - - //Copy Bitmap into bitmap_buff - for(int row = 0; row < _header.biHeight; row++) - { - //printf("Row %i\n", row); - //fread(bitmap_buff[row], sizeof(char), row_size, bitmap); - for(int col = 0; col < _header.biWidth; col++) - fread(&bitmap_buff[row][col], 1, 3, _file); - - for(int i = 0; i < row_size - (_header.biWidth * 3); i++) //read excess NULL-Bytes - fgetc(_file); - } - - ret.x = _header.biWidth; - ret.y = _header.biHeight < 0 ? -_header.biHeight: _header.biHeight; - - ret.R = malloc(sizeof(*ret.R) * ret.x); - ret.G = malloc(sizeof(*ret.G) * ret.x); - ret.B = malloc(sizeof(*ret.B) * ret.x); - for(int i = 0; i < ret.x; i++) - { - ret.R[i] = malloc(sizeof(*ret.R[i]) * ret.y); - ret.G[i] = malloc(sizeof(*ret.G[i]) * ret.y); - ret.B[i] = malloc(sizeof(*ret.B[i]) * ret.y); - } - - for(int y = 0; y < ret.y; y++) - { - for(int x = 0; x < ret.x; x++) - { - int row = _header.biHeight > 0 ? (ret.y - 1) - y : y; - - ret.R[x][y] = (bitmap_buff[row][x] & 0xff0000)>>16; - ret.G[x][y] = (bitmap_buff[row][x] & 0x00ff00)>>8; - ret.B[x][y] = (bitmap_buff[row][x] & 0x0000ff); - } - } - - for(int i = 0; i < ret.y; i++) - free(bitmap_buff[i]); - free(bitmap_buff); - - return ret; -} diff --git a/bitmap.h b/bitmap.h deleted file mode 100644 index d222ffb..0000000 --- a/bitmap.h +++ /dev/null @@ -1,70 +0,0 @@ -#ifndef _BITMAP_H_ -#define _BITMAP_H_ - -#include -#include -#include - -#define _HEADER_SIZE 54 //Fileheader + infoheader -#define IDENTIFIER 0x424d //BM BitMap identifier - -//Address Definitions -#define BF_TYPE 0x00 -#define BF_SIZE 0x02 -#define BF_OFF_BITS 0x0a - -#define BI_SIZE 0x0e -#define BI_WIDTH 0x12 -#define BI_HEIGHT 0x16 -#define BI_BIT_COUNT 0x1c -#define BI_COMPRESSION 0x1e -#define BI_SIZE_IMAGE 0x22 -#define BI_CLR_USED 0x2e -#define BI_CLR_IMPORTANT 0x32 - -#define R(x) (0xff0000 & x) >> 16 -#define G(x) (0x00ff00 & x) >> 8 -#define B(x) (0x0000ff & x) - -struct bitmap_file_header -{ - uint8_t error; - - uint16_t bfType; - uint32_t bfSize; - uint32_t bfOffBits; - - uint32_t biSize; - int32_t biWidth; - int32_t biHeight; - uint16_t biBitCount; - uint32_t biCompression; - uint32_t biSizeImage; - uint32_t biClrUsed; - uint32_t biClrImportant; - - unsigned char *tables; - uint32_t tablesc; -}; - -struct bitmap_pixel_data -{ - unsigned int x,y; - uint8_t **R; - uint8_t **G; - uint8_t **B; - - uint8_t error; -}; - - -uint32_t bitmap_flip_byte(unsigned char* _v, int _c); - -struct bitmap_pixel_data bitmap_read(char *_file); - -struct bitmap_file_header bitmap_read_file_header(FILE *_file); - -struct bitmap_pixel_data bitmap_read_pixel_data(FILE *_file, struct bitmap_file_header _header); - - -#endif /* end of include guard: _BITMAP_H_ */ diff --git a/character.c b/character.c deleted file mode 100644 index 658f0be..0000000 --- a/character.c +++ /dev/null @@ -1,10 +0,0 @@ -#include "character.h" - -const char character_luminance_map [] = {' ', ' ', '.', ',', '`', '-', '~', '"', '*', ':', ';', '<', '!', '/', '?', '%', '&', '=', '$', '#'}; -//const char map[] = {' ', '`', '.', ',', ':', ';', '\"', '+', '#', '@'}; - -char calc_char(uint8_t _c , uint8_t _min, uint8_t _max) -{ - float c = (float)(_c) / (_max - _min); - return character_luminance_map [(int)((sizeof(character_luminance_map)-1) * (c))]; -} diff --git a/character.h b/character.h deleted file mode 100644 index 7e17cd7..0000000 --- a/character.h +++ /dev/null @@ -1,12 +0,0 @@ -#ifndef _CHARACTER_H_ -#define _CHARACTER_H_ - -#include - -//Both maps produce very different results -const char character_luminance_map [] ; - -//Select Char based on 1B brightness Value -char calc_char(uint8_t _c, uint8_t _min, uint8_t _max); - -#endif //_CHARACTER_H_ diff --git a/color.c b/color.c deleted file mode 100644 index d822d56..0000000 --- a/color.c +++ /dev/null @@ -1,74 +0,0 @@ -#include "color.h" - -struct console_color colors[] = { //Standard VGA colors - {0, 0, 0, "30"}, //Black - {170, 0, 0, "31"}, //red - {0, 170, 0, "32"}, //Green - {170, 85, 0, "33"}, //Brown - {0, 0, 170, "34"}, //blue - {170, 0, 170, "35"}, //Magenta - {0, 170, 170, "36"}, //Cyan - {170,170,170, "37"}, //Grey - {85,85,85, "30;1"}, - {255,85,85, "31;1"}, - {85,255,85, "32;1"}, - {255,255,85, "33;1"}, - {85,85,255, "34;1"}, - {255,85,255, "35;1"}, - {85,255,255, "36;1"}, - {255, 255, 255, "37;1"} -}; - -uint8_t rgb_avg(uint8_t R, uint8_t G, uint8_t B) -{ - uint8_t ret; - - ret = sqrt( 0.299*pow(R,2) + 0.587*pow(G,2) + 0.114*pow(B,2) ); //(char)(R+R+B+G+G+G)/6; - - return ret; -} - -char* calc_col(uint8_t R, uint8_t G, uint8_t B) -{ - unsigned int nearest_num = 0; - uint8_t a2[3]; - a2[0] = colors[0].R; - a2[1] = colors[0].G; - a2[2] = colors[0].B; - - uint8_t a1[] = {R,G,B}; - - //Normalize the color - //Does not really work all that well - /*while(a1[0] < 255 && a1[1] < 255 && a1[2] < 255) - { - a1[0]++; - a1[1]++; - a1[2]++; - }*/ - - float nearest_val = distance( a1, a2 ); - - for( unsigned int i = 1; i < _COLORS_SIZE; i++) - { - a2[0] = colors[i].R; - a2[1] = colors[i].G; - a2[2] = colors[i].B; - - float dist = distance(a1, a2); - if(dist < nearest_val){ - nearest_num = i; - nearest_val = dist; - } - } - return colors[ nearest_num ].no; -} -char* calc_col_ansi(uint8_t R, uint8_t G, uint8_t B) -{ - int num = 36 * (R/51) + 6 * (G/51) + (B/51); - char *c = malloc(9); - snprintf( c, 6, "38;5;" ); - snprintf( c + 5, 4, "%i", num + 16 ); - - return c; -} diff --git a/color.h b/color.h deleted file mode 100644 index 10d376e..0000000 --- a/color.h +++ /dev/null @@ -1,33 +0,0 @@ -#ifndef _COLOR_H_ -#define _COLOR_H_ - -#include -#include -#include -#include - -#include "m.h" - -#define _COLORS_SIZE 16u - -struct console_color -{ - uint8_t R; - uint8_t G; - uint8_t B; - - char *no; -}; - -struct console_color colors[ _COLORS_SIZE ]; - -//Calculate luminance -//Order LSB first: BGR -uint8_t rgb_avg(uint8_t R, uint8_t G, uint8_t B); - -//Get nearest printable color in console -char *calc_col(uint8_t R, uint8_t G, uint8_t B); - -char *calc_col_ansi(uint8_t R, uint8_t G, uint8_t B); - -#endif //_COLOR_H_ diff --git a/m.c b/m.c deleted file mode 100644 index b1401f1..0000000 --- a/m.c +++ /dev/null @@ -1,22 +0,0 @@ -#include "m.h" - -uint8_t avg(int argc, uint8_t *argv) -{ - uint8_t ret = 0; - uint64_t sum = 0; - - for(int i = 0; i < argc; i++) - sum += (uint64_t)argv[i]; - - ret = (char)(sum / argc); - - return ret; -}//avg - - -float distance(uint8_t _1[3], uint8_t _2[3]) -{ - return fabs( sqrt( pow((double)_2[0] - (double)_1[0], 2) + - pow((double)_2[1] - (double)_1[1], 2) + - pow((double)_2[2] - (double)_1[2], 2) ) ); -} diff --git a/m.h b/m.h deleted file mode 100644 index 25aff9e..0000000 --- a/m.h +++ /dev/null @@ -1,14 +0,0 @@ -#ifndef _M_H_ -#define _M_H_ - -#include -#include - - -//Calculate average -uint8_t avg(int argc, uint8_t *argv); - -//Distance of 2 3d vectors -float distance(uint8_t _1[3], uint8_t _2[3]); - -#endif diff --git a/main.c b/main.c deleted file mode 100644 index b8bf074..0000000 --- a/main.c +++ /dev/null @@ -1,235 +0,0 @@ -#include -#include -#include -#include -#include - -#include "bitmap.h" -#include "character.h" -#include "m.h" -#include "color.h" - -#ifdef _DEBUG -#warning "Compiling with DEBUG" -#define DEBUG_PRINTF(...) { printf(__VA_ARGS__); } -#else -#define DEBUG_PRINTF(...) { } -#endif - -#define CHAR_SIZE_X 2 //How many pixels should form one ASCII char? -#define CHAR_SIZE_Y (2 * CHAR_SIZE_X) - -struct prog_param -{ - char *filename; - unsigned int charsize_x; - unsigned int charsize_y; - uint8_t color; -}; - -struct prog_param parse_args(int argc, char *argv[]); - -void print_help( void ); - -int main(int argc, char *argv[]) -{ - struct prog_param args = parse_args(argc, argv); - - //Stores a luminance array - uint8_t **ascii_buff; - //Stores a color array - char* **col_buff; - - uint8_t b_max = 0x00; - uint8_t b_min = 0xff; - - struct bitmap_pixel_data bitmap; - - bitmap = bitmap_read(args.filename); - - if(bitmap.error) { - printf("Error reading file\n"); - return 1; - } - - //x and y size of ASCII-image - unsigned int size_x,size_y; - size_x = bitmap.x / args.charsize_x; - size_y = bitmap.y / args.charsize_y; - - DEBUG_PRINTF("Output size: %u x %u\n", size_x, size_y); - - //Where the chars are stored - ascii_buff = malloc(sizeof(*ascii_buff) * size_x); - for (int i = 0; i < size_x; i++) - ascii_buff[i] = malloc(sizeof(ascii_buff[i]) * size_y); - - //Where the color is stored, if activated - if(args.color) { - col_buff = malloc(sizeof(*col_buff) * size_x); - for (int i = 0; i < size_x; i++) - col_buff[i] = malloc(sizeof(col_buff[i]) * size_y); - } - - //Nest thine Lööps - //Very not optimal Variable names!!!!!!!!!!!!! - // - //For every size_x * size_y block: calculate average values of pixel blocks - for(unsigned int x = 0; x < size_x; x++) { - for(unsigned int y = 0; y < size_y; y++) { - uint8_t brightness [ args.charsize_x ][ args.charsize_y ]; //Average brightness of every pixel - uint8_t cc[ 3 ][ args.charsize_x * args.charsize_y ]; //RGB Values of Pixels - unsigned int cc_counter = 0; - - //Iterate through Pixel block - for(unsigned int row_c = 0; row_c < args.charsize_y; row_c++) { - unsigned int row = y * args.charsize_y + row_c; //Actual position in Bitmap - - for(unsigned int col_c = 0; col_c < args.charsize_x; col_c++) { - unsigned int col = x * args.charsize_x + col_c; //Actual position in bitmap - - brightness[col_c][row_c] = rgb_avg( - bitmap.R[col][row], - bitmap.G[col][row], - bitmap.B[col][row]); - - if(args.color) { - cc[0][cc_counter] = bitmap.R[col][row]; - cc[1][cc_counter] = bitmap.G[col][row]; - cc[2][cc_counter] = bitmap.B[col][row]; - cc_counter++; - }//if - }//for col_c - }//for row_c - - ascii_buff[x][y] = avg(args.charsize_x * args.charsize_y, *brightness); - if(args.color == 1) { - col_buff[x][y] = calc_col( - (uint8_t)avg(args.charsize_x * args.charsize_y, cc[0]), - (uint8_t)avg(args.charsize_x * args.charsize_y, cc[1]), - (uint8_t)avg(args.charsize_x * args.charsize_y, cc[2])); - } else if(args.color == 2) { - col_buff[x][y] = calc_col_ansi( - (uint8_t)avg(args.charsize_x * args.charsize_y, cc[0]), - (uint8_t)avg(args.charsize_x * args.charsize_y, cc[1]), - (uint8_t)avg(args.charsize_x * args.charsize_y, cc[2])); - } - - if((uint8_t)ascii_buff[x][y] < b_min) - b_min = ascii_buff[x][y]; - if((uint8_t)ascii_buff[x][y] > b_max) - b_max = ascii_buff[x][y]; - }//for y - }//for x - - DEBUG_PRINTF("Brightness Values: Min: %u Max: %u\n", b_min, b_max); - - if(args.color) - printf("\e[0m");//Default colors - - //Print buffer - for(int y = 0; y 0 Data starts with last row!! + + //Allocate 2D array + //!! + //bitmap_buff indeces are flipped!! [y][x]!!!!! + bitmap_buff = malloc(sizeof(*bitmap_buff) * _header.biHeight); + for(int i = 0; i < ret.y; i++) + { + bitmap_buff[i] = malloc(sizeof(*bitmap_buff[i]) * _header.biWidth); + } + + //Copy Bitmap into bitmap_buff + for(int row = 0; row < _header.biHeight; row++) + { + //printf("Row %i\n", row); + //fread(bitmap_buff[row], sizeof(char), row_size, bitmap); + for(int col = 0; col < _header.biWidth; col++) + fread(&bitmap_buff[row][col], 1, 3, _file); + + for(int i = 0; i < row_size - (_header.biWidth * 3); i++) //read excess NULL-Bytes + fgetc(_file); + } + + ret.x = _header.biWidth; + ret.y = _header.biHeight < 0 ? -_header.biHeight: _header.biHeight; + + ret.R = malloc(sizeof(*ret.R) * ret.x); + ret.G = malloc(sizeof(*ret.G) * ret.x); + ret.B = malloc(sizeof(*ret.B) * ret.x); + for(int i = 0; i < ret.x; i++) + { + ret.R[i] = malloc(sizeof(*ret.R[i]) * ret.y); + ret.G[i] = malloc(sizeof(*ret.G[i]) * ret.y); + ret.B[i] = malloc(sizeof(*ret.B[i]) * ret.y); + } + + for(int y = 0; y < ret.y; y++) + { + for(int x = 0; x < ret.x; x++) + { + int row = _header.biHeight > 0 ? (ret.y - 1) - y : y; + + ret.R[x][y] = (bitmap_buff[row][x] & 0xff0000)>>16; + ret.G[x][y] = (bitmap_buff[row][x] & 0x00ff00)>>8; + ret.B[x][y] = (bitmap_buff[row][x] & 0x0000ff); + } + } + + for(int i = 0; i < ret.y; i++) + free(bitmap_buff[i]); + free(bitmap_buff); + + return ret; +} diff --git a/src/bitmap.h b/src/bitmap.h new file mode 100644 index 0000000..d222ffb --- /dev/null +++ b/src/bitmap.h @@ -0,0 +1,70 @@ +#ifndef _BITMAP_H_ +#define _BITMAP_H_ + +#include +#include +#include + +#define _HEADER_SIZE 54 //Fileheader + infoheader +#define IDENTIFIER 0x424d //BM BitMap identifier + +//Address Definitions +#define BF_TYPE 0x00 +#define BF_SIZE 0x02 +#define BF_OFF_BITS 0x0a + +#define BI_SIZE 0x0e +#define BI_WIDTH 0x12 +#define BI_HEIGHT 0x16 +#define BI_BIT_COUNT 0x1c +#define BI_COMPRESSION 0x1e +#define BI_SIZE_IMAGE 0x22 +#define BI_CLR_USED 0x2e +#define BI_CLR_IMPORTANT 0x32 + +#define R(x) (0xff0000 & x) >> 16 +#define G(x) (0x00ff00 & x) >> 8 +#define B(x) (0x0000ff & x) + +struct bitmap_file_header +{ + uint8_t error; + + uint16_t bfType; + uint32_t bfSize; + uint32_t bfOffBits; + + uint32_t biSize; + int32_t biWidth; + int32_t biHeight; + uint16_t biBitCount; + uint32_t biCompression; + uint32_t biSizeImage; + uint32_t biClrUsed; + uint32_t biClrImportant; + + unsigned char *tables; + uint32_t tablesc; +}; + +struct bitmap_pixel_data +{ + unsigned int x,y; + uint8_t **R; + uint8_t **G; + uint8_t **B; + + uint8_t error; +}; + + +uint32_t bitmap_flip_byte(unsigned char* _v, int _c); + +struct bitmap_pixel_data bitmap_read(char *_file); + +struct bitmap_file_header bitmap_read_file_header(FILE *_file); + +struct bitmap_pixel_data bitmap_read_pixel_data(FILE *_file, struct bitmap_file_header _header); + + +#endif /* end of include guard: _BITMAP_H_ */ diff --git a/src/character.c b/src/character.c new file mode 100644 index 0000000..658f0be --- /dev/null +++ b/src/character.c @@ -0,0 +1,10 @@ +#include "character.h" + +const char character_luminance_map [] = {' ', ' ', '.', ',', '`', '-', '~', '"', '*', ':', ';', '<', '!', '/', '?', '%', '&', '=', '$', '#'}; +//const char map[] = {' ', '`', '.', ',', ':', ';', '\"', '+', '#', '@'}; + +char calc_char(uint8_t _c , uint8_t _min, uint8_t _max) +{ + float c = (float)(_c) / (_max - _min); + return character_luminance_map [(int)((sizeof(character_luminance_map)-1) * (c))]; +} diff --git a/src/character.h b/src/character.h new file mode 100644 index 0000000..7e17cd7 --- /dev/null +++ b/src/character.h @@ -0,0 +1,12 @@ +#ifndef _CHARACTER_H_ +#define _CHARACTER_H_ + +#include + +//Both maps produce very different results +const char character_luminance_map [] ; + +//Select Char based on 1B brightness Value +char calc_char(uint8_t _c, uint8_t _min, uint8_t _max); + +#endif //_CHARACTER_H_ diff --git a/src/color.c b/src/color.c new file mode 100644 index 0000000..d822d56 --- /dev/null +++ b/src/color.c @@ -0,0 +1,74 @@ +#include "color.h" + +struct console_color colors[] = { //Standard VGA colors + {0, 0, 0, "30"}, //Black + {170, 0, 0, "31"}, //red + {0, 170, 0, "32"}, //Green + {170, 85, 0, "33"}, //Brown + {0, 0, 170, "34"}, //blue + {170, 0, 170, "35"}, //Magenta + {0, 170, 170, "36"}, //Cyan + {170,170,170, "37"}, //Grey + {85,85,85, "30;1"}, + {255,85,85, "31;1"}, + {85,255,85, "32;1"}, + {255,255,85, "33;1"}, + {85,85,255, "34;1"}, + {255,85,255, "35;1"}, + {85,255,255, "36;1"}, + {255, 255, 255, "37;1"} +}; + +uint8_t rgb_avg(uint8_t R, uint8_t G, uint8_t B) +{ + uint8_t ret; + + ret = sqrt( 0.299*pow(R,2) + 0.587*pow(G,2) + 0.114*pow(B,2) ); //(char)(R+R+B+G+G+G)/6; + + return ret; +} + +char* calc_col(uint8_t R, uint8_t G, uint8_t B) +{ + unsigned int nearest_num = 0; + uint8_t a2[3]; + a2[0] = colors[0].R; + a2[1] = colors[0].G; + a2[2] = colors[0].B; + + uint8_t a1[] = {R,G,B}; + + //Normalize the color + //Does not really work all that well + /*while(a1[0] < 255 && a1[1] < 255 && a1[2] < 255) + { + a1[0]++; + a1[1]++; + a1[2]++; + }*/ + + float nearest_val = distance( a1, a2 ); + + for( unsigned int i = 1; i < _COLORS_SIZE; i++) + { + a2[0] = colors[i].R; + a2[1] = colors[i].G; + a2[2] = colors[i].B; + + float dist = distance(a1, a2); + if(dist < nearest_val){ + nearest_num = i; + nearest_val = dist; + } + } + return colors[ nearest_num ].no; +} +char* calc_col_ansi(uint8_t R, uint8_t G, uint8_t B) +{ + int num = 36 * (R/51) + 6 * (G/51) + (B/51); + char *c = malloc(9); + snprintf( c, 6, "38;5;" ); + snprintf( c + 5, 4, "%i", num + 16 ); + + return c; +} diff --git a/src/color.h b/src/color.h new file mode 100644 index 0000000..10d376e --- /dev/null +++ b/src/color.h @@ -0,0 +1,33 @@ +#ifndef _COLOR_H_ +#define _COLOR_H_ + +#include +#include +#include +#include + +#include "m.h" + +#define _COLORS_SIZE 16u + +struct console_color +{ + uint8_t R; + uint8_t G; + uint8_t B; + + char *no; +}; + +struct console_color colors[ _COLORS_SIZE ]; + +//Calculate luminance +//Order LSB first: BGR +uint8_t rgb_avg(uint8_t R, uint8_t G, uint8_t B); + +//Get nearest printable color in console +char *calc_col(uint8_t R, uint8_t G, uint8_t B); + +char *calc_col_ansi(uint8_t R, uint8_t G, uint8_t B); + +#endif //_COLOR_H_ diff --git a/src/m.c b/src/m.c new file mode 100644 index 0000000..b1401f1 --- /dev/null +++ b/src/m.c @@ -0,0 +1,22 @@ +#include "m.h" + +uint8_t avg(int argc, uint8_t *argv) +{ + uint8_t ret = 0; + uint64_t sum = 0; + + for(int i = 0; i < argc; i++) + sum += (uint64_t)argv[i]; + + ret = (char)(sum / argc); + + return ret; +}//avg + + +float distance(uint8_t _1[3], uint8_t _2[3]) +{ + return fabs( sqrt( pow((double)_2[0] - (double)_1[0], 2) + + pow((double)_2[1] - (double)_1[1], 2) + + pow((double)_2[2] - (double)_1[2], 2) ) ); +} diff --git a/src/m.h b/src/m.h new file mode 100644 index 0000000..25aff9e --- /dev/null +++ b/src/m.h @@ -0,0 +1,14 @@ +#ifndef _M_H_ +#define _M_H_ + +#include +#include + + +//Calculate average +uint8_t avg(int argc, uint8_t *argv); + +//Distance of 2 3d vectors +float distance(uint8_t _1[3], uint8_t _2[3]); + +#endif diff --git a/src/main.c b/src/main.c new file mode 100644 index 0000000..b8bf074 --- /dev/null +++ b/src/main.c @@ -0,0 +1,235 @@ +#include +#include +#include +#include +#include + +#include "bitmap.h" +#include "character.h" +#include "m.h" +#include "color.h" + +#ifdef _DEBUG +#warning "Compiling with DEBUG" +#define DEBUG_PRINTF(...) { printf(__VA_ARGS__); } +#else +#define DEBUG_PRINTF(...) { } +#endif + +#define CHAR_SIZE_X 2 //How many pixels should form one ASCII char? +#define CHAR_SIZE_Y (2 * CHAR_SIZE_X) + +struct prog_param +{ + char *filename; + unsigned int charsize_x; + unsigned int charsize_y; + uint8_t color; +}; + +struct prog_param parse_args(int argc, char *argv[]); + +void print_help( void ); + +int main(int argc, char *argv[]) +{ + struct prog_param args = parse_args(argc, argv); + + //Stores a luminance array + uint8_t **ascii_buff; + //Stores a color array + char* **col_buff; + + uint8_t b_max = 0x00; + uint8_t b_min = 0xff; + + struct bitmap_pixel_data bitmap; + + bitmap = bitmap_read(args.filename); + + if(bitmap.error) { + printf("Error reading file\n"); + return 1; + } + + //x and y size of ASCII-image + unsigned int size_x,size_y; + size_x = bitmap.x / args.charsize_x; + size_y = bitmap.y / args.charsize_y; + + DEBUG_PRINTF("Output size: %u x %u\n", size_x, size_y); + + //Where the chars are stored + ascii_buff = malloc(sizeof(*ascii_buff) * size_x); + for (int i = 0; i < size_x; i++) + ascii_buff[i] = malloc(sizeof(ascii_buff[i]) * size_y); + + //Where the color is stored, if activated + if(args.color) { + col_buff = malloc(sizeof(*col_buff) * size_x); + for (int i = 0; i < size_x; i++) + col_buff[i] = malloc(sizeof(col_buff[i]) * size_y); + } + + //Nest thine Lööps + //Very not optimal Variable names!!!!!!!!!!!!! + // + //For every size_x * size_y block: calculate average values of pixel blocks + for(unsigned int x = 0; x < size_x; x++) { + for(unsigned int y = 0; y < size_y; y++) { + uint8_t brightness [ args.charsize_x ][ args.charsize_y ]; //Average brightness of every pixel + uint8_t cc[ 3 ][ args.charsize_x * args.charsize_y ]; //RGB Values of Pixels + unsigned int cc_counter = 0; + + //Iterate through Pixel block + for(unsigned int row_c = 0; row_c < args.charsize_y; row_c++) { + unsigned int row = y * args.charsize_y + row_c; //Actual position in Bitmap + + for(unsigned int col_c = 0; col_c < args.charsize_x; col_c++) { + unsigned int col = x * args.charsize_x + col_c; //Actual position in bitmap + + brightness[col_c][row_c] = rgb_avg( + bitmap.R[col][row], + bitmap.G[col][row], + bitmap.B[col][row]); + + if(args.color) { + cc[0][cc_counter] = bitmap.R[col][row]; + cc[1][cc_counter] = bitmap.G[col][row]; + cc[2][cc_counter] = bitmap.B[col][row]; + cc_counter++; + }//if + }//for col_c + }//for row_c + + ascii_buff[x][y] = avg(args.charsize_x * args.charsize_y, *brightness); + if(args.color == 1) { + col_buff[x][y] = calc_col( + (uint8_t)avg(args.charsize_x * args.charsize_y, cc[0]), + (uint8_t)avg(args.charsize_x * args.charsize_y, cc[1]), + (uint8_t)avg(args.charsize_x * args.charsize_y, cc[2])); + } else if(args.color == 2) { + col_buff[x][y] = calc_col_ansi( + (uint8_t)avg(args.charsize_x * args.charsize_y, cc[0]), + (uint8_t)avg(args.charsize_x * args.charsize_y, cc[1]), + (uint8_t)avg(args.charsize_x * args.charsize_y, cc[2])); + } + + if((uint8_t)ascii_buff[x][y] < b_min) + b_min = ascii_buff[x][y]; + if((uint8_t)ascii_buff[x][y] > b_max) + b_max = ascii_buff[x][y]; + }//for y + }//for x + + DEBUG_PRINTF("Brightness Values: Min: %u Max: %u\n", b_min, b_max); + + if(args.color) + printf("\e[0m");//Default colors + + //Print buffer + for(int y = 0; y