#include #include #include #include #include #include #include #include #include #include #define conf_font "/usr/share/fonts/TTF/Inconsolata-Regular.ttf" float map(float value, float start1, float stop1, float start2, float stop2){ return start2 + (stop2 - start2) * ((value - start1) / (stop1 - start1)); } static int SDL_CalculatePitch(Uint32 format, int width) { int pitch; if (SDL_ISPIXELFORMAT_FOURCC(format) || SDL_BITSPERPIXEL(format) >= 8) { pitch = (width * SDL_BYTESPERPIXEL(format)); } else { pitch = ((width * SDL_BITSPERPIXEL(format)) + 7) / 8; } pitch = (pitch + 3) & ~3; /* 4-byte aligning for speed */ return pitch; } SDL_Texture *createText(char *string, SDL_Renderer *renderer, SDL_Rect *textRect,TTF_Font *font, SDL_Color color){ SDL_Surface *textSurface = TTF_RenderText_Solid_Wrapped(font,string,color,400); SDL_Texture *text = SDL_CreateTextureFromSurface(renderer, textSurface); SDL_QueryTexture(text, NULL, NULL, &textRect->w, &textRect->h); SDL_FreeSurface(textSurface); return text; } typedef struct{ char *file; int color; char *density; int height; int width; int char_size; int box_size; bool export; char *export_name; bool print; float brightness; bool printMultiColorVars; } Pargs; void arg_interpet(char *argv[], Pargs *pargs){ int i=1; if(argv[i]){ while (argv[i]) { if (strcmp(argv[i],"--help")==0){ printf("--help prints this message\n"); printf("-p print the ascii to terminal\n"); printf("-c [color] sets the color type. none, avg, color\n"); printf("-d [str] sets the characters to use\n"); printf("-w [width]\n"); printf("-h [height]\n"); printf("-s [size] sets the character size\n"); printf("-b [size] sets the box size\n"); printf("-o [file.png] exports the image\n"); printf("-B [brightness float] sets brightness\n"); printf("-C enables colorvars for ascii output. enable -p and perferable use -c color\n intended to be used for fastfetch\n"); printf("defaults \n none \n N@EW$9876543210?!abc;:+=-,._ \n width 900 \n height 900 \n char size 10 \n box size 10"); exit(0); } if (argv[i+1]){}else{ pargs->file=argv[i]; break; } if (strcmp(argv[i],"-p")==0){ pargs->print=true; } if (strcmp(argv[i],"-C")==0){ pargs->printMultiColorVars=true; } if (strcmp(argv[i],"-c")==0){ if(argv[i+2]){}else{ printf("you must specify a color with -C\n\n"); exit(1); } if(strcmp(argv[i+1],"none")==0){ pargs->color=0; } else if (strcmp(argv[i+1],"avg")==0) { pargs->color=1; } else if (strcmp(argv[i+1],"color")==0) { pargs->color=2; } else { printf("not a valid color type\n\n"); exit(1); } } if (strcmp(argv[i],"-d")==0){ if(argv[i+2]){}else{ printf("you must select a charset with -d \n\n"); exit(1); } pargs->density=argv[i+1]; } if (strcmp(argv[i],"-B")==0){ if(argv[i+2]){}else{ printf("you must select brightness with -B \n\n"); exit(1); } pargs->brightness=atof(argv[i+1]); } if (strcmp(argv[i],"-w")==0){ if(argv[i+2]){}else{ printf("you must set width -w \n\n"); exit(1); } pargs->width=atoi(argv[i+1]); } if (strcmp(argv[i],"-h")==0){ if(argv[i+2]){}else{ printf("you must set height -h \n\n"); exit(1); } pargs->height=atoi(argv[i+1]); } if (strcmp(argv[i],"-s")==0){ if(argv[i+2]){}else{ printf("you must set char_size with -s \n\n"); exit(1); } pargs->char_size=atoi(argv[i+1]); } if (strcmp(argv[i],"-b")==0){ if(argv[i+2]){}else{ printf("you must set box_size with -b \n\n"); exit(1); } pargs->box_size=atoi(argv[i+1]); } if (strcmp(argv[i],"-o")==0){ if(argv[i+2]){}else{ printf("you must set image export name with -o \n\n"); exit(1); } pargs->export=true; pargs->export_name=argv[i+1]; } argv++; } } else { printf("error, file not specified"); exit(1); } } SDL_Color hexToColor(char *str){ int r, g, b; sscanf(str, "%02x%02x%02x", &r, &g, &b); return (SDL_Color){r,g,b}; } float magnitude(float x, float y, float z) { return sqrt((pow(x,2) + pow(y,2) + pow(z,2))); } int getMultiColor(SDL_Color *color){ int colorCount=8; char **color_hexs=(char**)malloc(sizeof(char*)*colorCount); //for (int i=0; i<16; i++){ // color_hexs[i]=(char*)malloc(sizeof(char)*8); //} color_hexs[0]="000000"; color_hexs[1]="AA0000"; color_hexs[2]="00AA00"; color_hexs[3]="AA5500"; color_hexs[4]="0000AA"; color_hexs[5]="AA00AA"; color_hexs[6]="00AAAA"; color_hexs[7]="AAAAAA"; //color_hexs[8]="555555"; //color_hexs[9]="FF5555"; //color_hexs[10]="55FF55"; //color_hexs[11]="FFFF55"; //color_hexs[12]="5555FF"; //color_hexs[13]="FF55FF"; //color_hexs[14]="55FFFF"; //color_hexs[15]="FFFFFF"; //#000000 //#AA0000 //#00AA00 //#AA5500 //#0000AA //#AA00AA //#00AAAA //#AAAAAA //#555555 //#FF5555 //#55FF55 //#FFFF55 //#5555FF //#FF55FF //#55FFFF //#FFFFFF float colors[colorCount]; for (int i=0; ir-sel_col.r, (float)color->g-sel_col.g, (float)color->b-sel_col.b); } int sel=0; float last_dist=99999; for (int i=0; iwidth; textRect.h = parsed_args->height; SDL_Rect textRect2={0,0,0,0}; textRect2.w = textRect2.h = 10; //SDL_Rect *textRect2=malloc(sizeof(SDL_Rect)); //textRect2->w = textRect2->h = 10; SDL_Texture *textllure; textllure=IMG_LoadTexture(renderer,parsed_args->file); SDL_RenderCopy(renderer, textllure, NULL, &textRect); Uint32* Rpixels = (Uint32*)malloc(parsed_args->width * parsed_args->height * 2 * sizeof(Uint32)); int pitch = SDL_CalculatePitch(pix_format, parsed_args->width); //int a=SDL_RenderReadPixels(renderer, NULL, pix_format, Rpixels, parsed_args->width * sizeof(Uint32)); SDL_RenderReadPixels(renderer, NULL, pix_format, Rpixels, pitch); SDL_SetRenderDrawColor(renderer, 0, 0, 0, 255); SDL_RenderClear(renderer); char *sel_char; sel_char = (char *) malloc(sizeof(char) * 2); SDL_Texture *textllure2; const int divis=parsed_args->box_size; const int w2 = parsed_args->width / divis; const int h2 = parsed_args->height / divis; for (int y=0; yparsed_args->width){x2=parsed_args->width;} if(y2>parsed_args->height){y2=parsed_args->height;} const Uint32 pixelIndex= Rpixels[x2 + y2 * parsed_args->width]; uint8_t r2 = round(((pixelIndex >> 16) & 0xFF) * parsed_args->brightness); uint8_t g2 = round(((pixelIndex >> 8) & 0xFF) * parsed_args->brightness); uint8_t b2 = round((pixelIndex & 0xFF) * parsed_args->brightness); if(r2 > 255){ r2=255; } if(b2 > 255){ b2=255; } if(g2 > 255){ g2=255; } int avg = (r2 + g2 + b2) / 3; float inver=255-(avg)-1; if (inver>254){ inver=254; } if (inver<0){ inver=0; } const int charIndex = floor(map(inver,0,255,0,strlen(parsed_args->density))); textRect2.x = x2; textRect2.y = y2; SDL_Color color={255,255,255,255}; switch (parsed_args->color){ case 1: color.r=avg; color.b=avg; color.g=avg; break; case 2: color.r=r2; color.b=b2; color.g=g2; break; } sel_char[0]=parsed_args->density[charIndex]; sel_char[1]='\0'; if(parsed_args->print==true){ if(parsed_args->printMultiColorVars && sel_char[0] != ' '){ int charcol=getMultiColor(&color); printf("$%d",charcol); } printf("%s",sel_char); } textllure2=createText(sel_char, renderer, &textRect2, font, color); SDL_RenderCopy(renderer,textllure2,NULL, &textRect2); SDL_DestroyTexture(textllure2); } if(parsed_args->print==true){printf("\n");} } //SDL_SetHint(SDL_HINT_RENDER_SCALE_QUALITY, "0"); if(parsed_args->export==true){ SDL_Surface* pScreenShot = SDL_CreateRGBSurface(0, parsed_args->width, parsed_args->height, 32, 0x00ff0000, 0x0000ff00, 0x000000ff, 0x00000000); //SDL_Surface* pScreenShot = SDL_CreateRGBSurface(0, parsed_args->width, parsed_args->height, 32, 0,0,0,0); if(pScreenShot) { // Read the pixels from the current render target and save them onto the surface //SDL_RenderReadPixels(renderer, NULL, SDL_GetWindowPixelFormat(window), pScreenShot->pixels, pScreenShot->pitch); SDL_RenderReadPixels(renderer, NULL, SDL_GetWindowPixelFormat(window), pScreenShot->pixels, pScreenShot->pitch); char* name=parsed_args->export_name; // Create the bmp screenshot file IMG_SavePNG(pScreenShot, name); // Destroy the screenshot surface SDL_FreeSurface(pScreenShot); } } SDL_RenderPresent(renderer); SDL_UpdateWindowSurface(window); free(Rpixels); free(sel_char); SDL_DestroyTexture(textllure); SDL_DestroyTexture(textllure2); } int main(int argc, char *argv[]) { Pargs parsed_args={"",0,"N@EW$9876543210?!abc;:+=-,._ ",900,900,10,10,false,"",false,1}; arg_interpet(argv,&parsed_args); if (SDL_InitSubSystem(SDL_INIT_VIDEO) < 0) SDL_Log("SDL fails to initialize! %s\n", SDL_GetError()); TTF_Init(); SDL_Window *window = SDL_CreateWindow("SDL Ascii", SDL_WINDOWPOS_CENTERED, SDL_WINDOWPOS_CENTERED, parsed_args.width, parsed_args.height, SDL_WINDOW_SHOWN); if (!window) { printf("Failed to create window: %s\n", SDL_GetError()); } SDL_Renderer *renderer = SDL_CreateRenderer(window,-1,SDL_RENDERER_SOFTWARE); if (!renderer) { printf("Failed to create renderer: %s\n", SDL_GetError()); } uint32_t wnd_pix_fmt = SDL_GetWindowPixelFormat(window); TTF_Font *font = TTF_OpenFont(conf_font,parsed_args.char_size); draw(renderer,window,wnd_pix_fmt,font,&parsed_args); bool quit = false; SDL_Event e; while (!quit) { while (SDL_PollEvent(&e)) { if (e.type == SDL_QUIT) { quit = true; } } SDL_Delay(10); } SDL_DestroyWindow(window); //free window and windowSurface SDL_DestroyRenderer(renderer); TTF_CloseFont(font); SDL_VideoQuit(); TTF_Quit(); SDL_Quit(); return 0; }