mirror of
https://git.faggot-chan.online/imagesortc/
synced 2026-11-04 23:35:44 +01:00
324 lines
11 KiB
C
324 lines
11 KiB
C
#include <SDL2/SDL.h>
|
|
#include <SDL2/SDL_assert.h>
|
|
#include <SDL2/SDL_image.h>
|
|
#include <SDL2/SDL_keyboard.h>
|
|
#include <SDL2/SDL_scancode.h>
|
|
#include <SDL2/SDL_surface.h>
|
|
#include <SDL2/SDL_ttf.h>
|
|
#include <SDL2/SDL_render.h>
|
|
#include <sys/stat.h>
|
|
#include <stdio.h>
|
|
#include <stdbool.h>
|
|
#include <string.h>
|
|
#include <stdlib.h>
|
|
#include <dirent.h>
|
|
|
|
|
|
#define WINTITLE "sorting..."
|
|
#define FONTSIZE 80
|
|
#define FONTPATH "font/FreeSans.ttf"
|
|
|
|
SDL_Color textcolor = { 255, 255, 255, 255 };
|
|
|
|
typedef struct displayer {
|
|
SDL_Window *window;
|
|
SDL_Renderer *renderer;
|
|
SDL_Texture *background;
|
|
TTF_Font *font;
|
|
}displayer;
|
|
|
|
|
|
void sdlcleanup(displayer *displayerer, char **images, DIR *dir, int count, int exitstatus){
|
|
|
|
closedir(dir);
|
|
int i = 0;
|
|
while(i < count){
|
|
free(images[i]);
|
|
i++;
|
|
}
|
|
free(images);
|
|
|
|
TTF_CloseFont(displayerer->font);
|
|
SDL_DestroyTexture(displayerer->background);
|
|
SDL_DestroyRenderer(displayerer->renderer);
|
|
SDL_DestroyWindow(displayerer->window);
|
|
TTF_Quit();
|
|
IMG_Quit();
|
|
SDL_Quit();
|
|
exit(exitstatus);
|
|
}
|
|
|
|
bool sdlinit(displayer *displayerer){
|
|
|
|
|
|
|
|
if (SDL_Init(SDL_INIT_EVERYTHING)){
|
|
fprintf(stderr, "failed to initialize SDL: %s\n", SDL_GetError());
|
|
return true;
|
|
}
|
|
|
|
|
|
int imginit = IMG_Init(IMG_INIT_PNG | IMG_INIT_JPG);
|
|
if ((imginit & (IMG_INIT_PNG | IMG_INIT_JPG)) != (IMG_INIT_PNG | IMG_INIT_JPG)){
|
|
fprintf(stderr, "failed to initialize SDL: %s\n", IMG_GetError());
|
|
return true;
|
|
}
|
|
|
|
if (TTF_Init()){
|
|
fprintf(stderr, "failed to initialize ttf: %s\n", TTF_GetError());
|
|
return true;
|
|
}
|
|
|
|
displayerer->font = TTF_OpenFont(FONTPATH, FONTSIZE);
|
|
if(!displayerer->font) {
|
|
fprintf(stderr, "failed to load font: %s\n", TTF_GetError());
|
|
return true;
|
|
}
|
|
|
|
displayerer->window = SDL_CreateWindow(
|
|
WINTITLE,SDL_WINDOWPOS_CENTERED,
|
|
SDL_WINDOWPOS_CENTERED, 0, 0,
|
|
SDL_WINDOW_SHOWN | SDL_WINDOW_RESIZABLE |
|
|
SDL_WINDOW_ALWAYS_ON_TOP);
|
|
if(!displayerer->window){
|
|
fprintf(stderr, "failed to create window: %s\n", SDL_GetError());
|
|
return true;
|
|
}
|
|
|
|
displayerer->renderer = SDL_CreateRenderer(displayerer->window, -1, 0);
|
|
if(!displayerer->renderer){
|
|
fprintf(stderr, "failed to create renderer: %s\n", SDL_GetError());
|
|
return true;
|
|
}
|
|
|
|
|
|
return false;
|
|
}
|
|
|
|
|
|
bool loadimages(displayer *displayerer,char *who){
|
|
|
|
displayerer->background = IMG_LoadTexture(displayerer->renderer, who);
|
|
|
|
if(!displayerer->background) {
|
|
fprintf(stderr, "failed to load image: %s\n", IMG_GetError());
|
|
return true;
|
|
}
|
|
|
|
return false;
|
|
}
|
|
|
|
|
|
int main(int argc, char **argv){
|
|
|
|
struct displayer displayerer = {
|
|
.window = NULL,
|
|
.renderer = NULL,
|
|
.background = NULL,
|
|
.font = NULL,
|
|
};
|
|
|
|
const char *path = (argc > 1) ? argv[1] : ".";
|
|
|
|
char **images = malloc(16 * sizeof(char *));
|
|
DIR *dir = opendir(path);
|
|
if(!dir){
|
|
fprintf(stderr, "%s: can't open dir %s", argv[0], argv[1]);
|
|
return 1;
|
|
}
|
|
|
|
struct dirent *files;
|
|
int count = 0;
|
|
char buf[1024];
|
|
int capacity = 16; //tiny because i actally wanna realloc
|
|
while ((files = readdir(dir)) != NULL) {
|
|
char *ext = strrchr(files->d_name, '.');
|
|
if (ext == NULL) continue;
|
|
if (strcasecmp(ext, ".png") != 0 && strcasecmp(ext, ".jpg") != 0 && strcasecmp(ext, ".jpeg") != 0) continue;
|
|
|
|
if(count == capacity){
|
|
capacity *= 2;
|
|
images = realloc(images, capacity * sizeof(char *));
|
|
if(images == NULL){
|
|
sdlcleanup(&displayerer, images, dir, count, EXIT_FAILURE);
|
|
}
|
|
}
|
|
|
|
|
|
snprintf(buf, sizeof(buf), "%s/%s", path, files->d_name); //i hate how c does things
|
|
images[count] = strdup(buf);
|
|
count++;
|
|
}
|
|
if(count == 0){
|
|
printf("erm idk what you did here but you probably ran the program in a dir with no .pngs or .jpgs... hopefully you're not gonna segfault here");
|
|
sdlcleanup(&displayerer, images, dir, count, EXIT_FAILURE);
|
|
}
|
|
|
|
char saveddir[1024], otherdir[1024], deletedir[1024];
|
|
snprintf(saveddir, sizeof(saveddir), "%s/saved", path);
|
|
snprintf(otherdir, sizeof(otherdir), "%s/other", path);
|
|
snprintf(deletedir, sizeof(deletedir), "%s/delete", path);
|
|
|
|
mkdir(saveddir, 0755);
|
|
mkdir(otherdir, 0755);
|
|
mkdir(deletedir, 0755);
|
|
|
|
if(sdlinit(&displayerer)){
|
|
sdlcleanup(&displayerer, images, dir, count, EXIT_FAILURE);
|
|
}
|
|
|
|
int whichone = 1; //0 means nothing it doesn't load lol
|
|
int typing = 0;
|
|
int len;
|
|
char textbuf[256];
|
|
|
|
loadimages(&displayerer, images[whichone]);
|
|
|
|
while(true){
|
|
|
|
SDL_Event event;
|
|
while(SDL_PollEvent(&event)){
|
|
switch(event.type){
|
|
default : break;
|
|
case SDL_QUIT:
|
|
sdlcleanup(&displayerer, images, dir, count, EXIT_SUCCESS); break;
|
|
case SDL_TEXTINPUT:
|
|
strcat(textbuf, event.text.text);
|
|
break;
|
|
case SDL_TEXTEDITING:
|
|
strcpy(textbuf, event.edit.text);
|
|
break;
|
|
|
|
case SDL_KEYDOWN : switch(event.key.keysym.scancode){
|
|
default: break;
|
|
|
|
case SDL_SCANCODE_BACKSPACE:
|
|
len = strlen(textbuf);
|
|
if (len > 0) {
|
|
textbuf[len - 1] = '\0';
|
|
}
|
|
break;
|
|
case SDL_SCANCODE_ESCAPE:
|
|
sdlcleanup(&displayerer, images, dir, count, EXIT_SUCCESS); break;
|
|
case SDL_SCANCODE_W:
|
|
if(!typing){
|
|
typing = 1;
|
|
textbuf[0] = '\0';
|
|
SDL_StartTextInput();
|
|
}
|
|
break;
|
|
case SDL_SCANCODE_RETURN:
|
|
if(typing){
|
|
typing = 0;
|
|
SDL_StopTextInput();
|
|
char *ext = strrchr(images[whichone], '.');
|
|
char savedbuf[1024];
|
|
snprintf(savedbuf, sizeof(savedbuf), "%s/%s%s", saveddir, textbuf, ext ? ext : "");
|
|
rename(images[whichone], savedbuf);
|
|
if(whichone + 1 < count){
|
|
whichone++;
|
|
SDL_DestroyTexture(displayerer.background);
|
|
loadimages(&displayerer, images[whichone]);
|
|
}
|
|
}
|
|
break;
|
|
case SDL_SCANCODE_Q:
|
|
if(!typing){if(whichone + 1 < count){
|
|
whichone++;
|
|
SDL_DestroyTexture(displayerer.background);}
|
|
loadimages(&displayerer, images[whichone]);
|
|
printf("loaded: %s\n", images[whichone]);
|
|
}else { whichone = 0;}
|
|
break;
|
|
case SDL_SCANCODE_A:
|
|
if(!typing){if(whichone > 1){
|
|
whichone--;
|
|
SDL_DestroyTexture(displayerer.background);
|
|
loadimages(&displayerer, images[whichone]);
|
|
printf("loaded: %s\n", images[whichone]);
|
|
}
|
|
}
|
|
break;
|
|
case SDL_SCANCODE_S:
|
|
if(!typing){
|
|
char otherbuf[1024];
|
|
snprintf(otherbuf, sizeof(otherbuf), "%s/%s", otherdir, strrchr(images[whichone], '/') + 1);
|
|
rename(images[whichone], otherbuf);
|
|
if(whichone + 1 < count){
|
|
whichone++;
|
|
SDL_DestroyTexture(displayerer.background);
|
|
loadimages(&displayerer, images[whichone]);
|
|
}
|
|
}
|
|
break;
|
|
case SDL_SCANCODE_D:
|
|
if(!typing){
|
|
char otherbuf[1024];
|
|
snprintf(otherbuf, sizeof(otherbuf), "%s/%s", deletedir, strrchr(images[whichone], '/') + 1);
|
|
rename(images[whichone], otherbuf);
|
|
if(whichone + 1 < count){
|
|
whichone++;
|
|
SDL_DestroyTexture(displayerer.background);
|
|
loadimages(&displayerer, images[whichone]);
|
|
}
|
|
}
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
|
|
SDL_RenderClear(displayerer.renderer);
|
|
|
|
//is it wise to calculate this each frame? no. will i optimize it? no
|
|
//actually yeah because i can resize the window
|
|
int imgw, imgh,winw, winh;
|
|
SDL_QueryTexture(displayerer.background, NULL, NULL, &imgw, &imgh);
|
|
SDL_GetRendererOutputSize(displayerer.renderer, &winw, &winh);
|
|
|
|
float scalex = (float)winw / imgw;
|
|
float scaley = (float)winh / imgh;
|
|
float scale = (scalex < scaley) ? scalex : scaley;
|
|
SDL_Rect dst = {
|
|
.w = (int)(imgw * scale),
|
|
.h = (int)(imgh * scale),
|
|
};
|
|
dst.x = (winw - dst.w) / 2;
|
|
dst.y = (winh - dst.h) / 2;
|
|
//if i was smarter i'd wrap this in another function
|
|
|
|
SDL_RenderCopy(displayerer.renderer, displayerer.background, NULL, &dst);
|
|
|
|
SDL_Rect angle = {
|
|
.w = (int)winw,
|
|
.h = (int) 100,
|
|
.y = (int)(winh)/2-50,
|
|
.x = (int) 0,
|
|
};
|
|
|
|
if(typing){
|
|
SDL_SetRenderDrawColor(displayerer.renderer, 0, 0, 0, 255);
|
|
SDL_RenderFillRect(displayerer.renderer, &angle);
|
|
|
|
SDL_Surface *surf = TTF_RenderText_Solid(displayerer.font, textbuf[0] ? textbuf : " ", textcolor);
|
|
SDL_Texture *tex = SDL_CreateTextureFromSurface(displayerer.renderer, surf);
|
|
int tw, th;
|
|
SDL_QueryTexture(tex, NULL, NULL, &tw, &th);
|
|
SDL_Rect textrect = {
|
|
.x = winw/2 - tw/2,
|
|
.y = winh/2 - th/2,
|
|
.w = tw,
|
|
.h = th,
|
|
};
|
|
SDL_RenderCopy(displayerer.renderer, tex, NULL, &textrect);
|
|
SDL_DestroyTexture(tex);
|
|
}
|
|
|
|
SDL_RenderPresent(displayerer.renderer);
|
|
|
|
SDL_Delay(8); //about 120 fps, worthless since this is not really a game
|
|
}
|
|
|
|
sdlcleanup(&displayerer, images, dir, count, EXIT_SUCCESS);
|
|
return 0;
|
|
}
|