diff options
| author | iceyrazor <iceyrazor@mailfence.com> | 2025-05-16 19:13:02 -0500 |
|---|---|---|
| committer | iceyrazor <iceyrazor@mailfence.com> | 2025-05-16 19:13:02 -0500 |
| commit | 801c119f1f44ea7509e705af416ecb23e5167e28 (patch) | |
| tree | f4b7279be37c99d14f7a3bfbda9901009bed645b | |
init but i didnt use git before hand so untracked stuff has happened
| -rw-r--r-- | .gitignore | 2 | ||||
| -rwxr-xr-x | LICENSE | 21 | ||||
| -rwxr-xr-x | Makefile | 7 | ||||
| -rw-r--r-- | README | 5 | ||||
| -rwxr-xr-x | main.c | 382 |
5 files changed, 417 insertions, 0 deletions
diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..7a89bf6 --- /dev/null +++ b/.gitignore @@ -0,0 +1,2 @@ +paladins.ttf +ascii @@ -0,0 +1,21 @@ +MIT License + +Copyright (c) 2025 iceyrazor + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. diff --git a/Makefile b/Makefile new file mode 100755 index 0000000..f8c88d3 --- /dev/null +++ b/Makefile @@ -0,0 +1,7 @@ +LIB= + +main: main.c + gcc -o ascii main.c -lSDL2 `sdl2-config --cflags --libs` -lSDL2_ttf -lSDL2_image -lm ${LIB} + +debug: main.c + gcc -o ascii main.c -lSDL2 `sdl2-config --cflags --libs` -lSDL2_ttf -lSDL2_image -lm ${LIB} -g -fsanitize=address @@ -0,0 +1,5 @@ +Makes ASCII from text using SDL2. Do --help for help + +Just a little project i wanted to make because ascii is cool. No plans to optimize this. It works fine. There're are definitely better terminal only based ones. + +You need to download the paladins.ttf font and put it in the same directory as this executable. Yes I'm lazy. @@ -0,0 +1,382 @@ +#include <SDL2/SDL_pixels.h> +#include <SDL2/SDL_render.h> +#include <SDL2/SDL_stdinc.h> +#include <stdio.h> +#include <string.h> +#include <stdlib.h> +#include <stdbool.h> +#include <math.h> + +#include <SDL2/SDL.h> +#include <SDL2/SDL_video.h> +#include <SDL2/SDL_image.h> +#include <SDL2/SDL_ttf.h> + + + +float map(float value, float start1, float stop1, float start2, float stop2){ + return start2 + (stop2 - start2) * ((value - start1) / (stop1 - start1)); +} + +void putPixelRGB(SDL_Renderer* renderer, int x, int y, unsigned char r,unsigned char g,unsigned char b){ +SDL_SetRenderDrawColor(renderer,(Uint8)r,(Uint8)g,(Uint8)b,255); +SDL_RenderDrawPoint(renderer,x,y); +} + + +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; +} 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("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){ + 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); + } + +} + +void draw(SDL_Renderer* renderer,SDL_Window* window, uint32_t pix_format,TTF_Font *font,Pargs *parsed_args){ + + SDL_Rect textRect; + memset(&textRect, 0, sizeof(SDL_Rect)); + textRect.w = parsed_args->width; + 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)); + int a=SDL_RenderReadPixels(renderer, NULL, pix_format, Rpixels, pitch); + + for (int width=0; width<=parsed_args->width; width++){ + for (int height=0; height<=parsed_args->height; height++){ + putPixelRGB(renderer, width, height, 0, 0, 0); + } + } + + 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; y<h2; y++){ + for (int x=0; x<w2; x++){ + int x2=x * divis; + int y2=y * divis; + if(x2>parsed_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; + int avg_conv=avg; + + 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){printf("%s",sel_char);} + //SDL_Log("%dx%d %d %d %s\n",width2,height2,avg_conv,charIndex,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 num[100]; + 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 Tutorial", 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("/usr/share/fonts/TTF/Inconsolata-Regular.ttf",parsed_args.char_size); + + + draw(renderer,window,wnd_pix_fmt,font,&parsed_args); + + + bool quit = false; + SDL_Event e; + bool mousedown=false; + int gmouseX=0; + int gmouseY=0; + while (!quit) { + while (SDL_PollEvent(&e)) { + if (e.type == SDL_QUIT) { + quit = true; + } + else if(e.type == SDL_MOUSEBUTTONDOWN){ + } else if(e.type==SDL_MOUSEBUTTONUP){ + } + gmouseX=e.button.x; + gmouseY=e.button.y; + } + float mouseoutX=gmouseX; + float mouseoutY=gmouseY; + if(mousedown==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; +} |
