initial push
This commit is contained in:
@@ -0,0 +1,19 @@
|
|||||||
|
# SimpleImageViewer
|
||||||
|
|
||||||
|
> View images fast and without any hocus pocus, sometimes less is better
|
||||||
|
|
||||||
|
## Disclaimer
|
||||||
|
The inspiration was a youtube video, i've watched the beginning and though to myself that this cannot be that hard to implement.
|
||||||
|
Of course it is not without usage, I will prepare the app to be hooked in Hyprland to launch the current photo stored in clipboard.
|
||||||
|
|
||||||
|
## Requirements
|
||||||
|
- SDL3
|
||||||
|
|
||||||
|
## Installations
|
||||||
|
#### Macos
|
||||||
|
- `brew install sdl3`
|
||||||
|
- clone this repo and navigate into it
|
||||||
|
- `gcc SimpleImageViewer.c -o SimpleImageViewer -Wall -Werror -o3 $(pkg-config --cflags --libs sdl3)` or with `clang`
|
||||||
|
|
||||||
|
#### Linux
|
||||||
|
- TODO
|
||||||
@@ -0,0 +1,165 @@
|
|||||||
|
#include <stdio.h>
|
||||||
|
#include <unistd.h>
|
||||||
|
#include <SDL3/SDL.h>
|
||||||
|
#include <SDL3/SDL_video.h>
|
||||||
|
#include <SDL3/SDL_mouse.h>
|
||||||
|
#include <SDL3/SDL_keyboard.h>
|
||||||
|
#include <SDL3/SDL_events.h>
|
||||||
|
#include <math.h>
|
||||||
|
|
||||||
|
#define STB_IMAGE_IMPLEMENTATION
|
||||||
|
#include "stb_image.h"
|
||||||
|
|
||||||
|
#define DESIRED_IMAGE_CHANNELS 4
|
||||||
|
|
||||||
|
typedef struct Image{
|
||||||
|
int x;
|
||||||
|
int y;
|
||||||
|
int channels;
|
||||||
|
unsigned char* pixels;
|
||||||
|
} Image;
|
||||||
|
|
||||||
|
Image load_image(const char* filepath){
|
||||||
|
Image image;
|
||||||
|
image.pixels = stbi_load(filepath, &image.x, &image.y, &image.channels, DESIRED_IMAGE_CHANNELS);
|
||||||
|
return image;
|
||||||
|
}
|
||||||
|
|
||||||
|
void free_image(Image* image){
|
||||||
|
if(image->pixels) stbi_image_free(image->pixels);
|
||||||
|
}
|
||||||
|
|
||||||
|
SDL_Window* create_window(const char* title, int w, int h){
|
||||||
|
const SDL_InitFlags init_flags = SDL_INIT_VIDEO | SDL_INIT_EVENTS;
|
||||||
|
const SDL_WindowFlags window_flags = SDL_WINDOW_BORDERLESS
|
||||||
|
// | SDL_WINDOW_MAXIMIZED
|
||||||
|
// | SDL_WINDOW_TRANSPARENT
|
||||||
|
// | SDL_WINDOW_ALWAYS_ON_TOP
|
||||||
|
| SDL_WINDOW_RESIZABLE
|
||||||
|
| SDL_WINDOW_KEYBOARD_GRABBED;
|
||||||
|
|
||||||
|
SDL_Init(init_flags);
|
||||||
|
|
||||||
|
/* Used when a larger window is wanted, image displaying is dynamically calculated
|
||||||
|
int display_count;
|
||||||
|
SDL_DisplayID* displays = SDL_GetDisplays(&display_count);
|
||||||
|
if(display_count == 0){
|
||||||
|
printf("%s\n", SDL_GetError());
|
||||||
|
printf("Could not get any displays!");
|
||||||
|
exit(5);
|
||||||
|
}
|
||||||
|
|
||||||
|
const SDL_DisplayMode* mode = SDL_GetDesktopDisplayMode(displays[0]);
|
||||||
|
if(!mode){
|
||||||
|
printf("Failed to get display information!");
|
||||||
|
exit(6);
|
||||||
|
}
|
||||||
|
*/
|
||||||
|
|
||||||
|
SDL_Window* window = SDL_CreateWindow(title, w, h, window_flags);
|
||||||
|
SDL_SetWindowAspectRatio(window, (float)w / (float)h, (float)w / (float)h);
|
||||||
|
|
||||||
|
return window;
|
||||||
|
}
|
||||||
|
|
||||||
|
SDL_Surface* get_surface_from_window(SDL_Window* window){
|
||||||
|
return SDL_GetWindowSurface(window);
|
||||||
|
}
|
||||||
|
|
||||||
|
void draw_image(SDL_Surface* surface, Image* image){
|
||||||
|
SDL_Rect pixel = { 0, 0, 1, 1 };
|
||||||
|
|
||||||
|
int center_x = ((surface->w + 1) / 2 - 1);
|
||||||
|
int center_y = ((surface->h + 1) / 2 - 1);
|
||||||
|
|
||||||
|
int dst_x = center_x - image->x / 2;
|
||||||
|
int dst_y = center_y - image->y / 2;
|
||||||
|
|
||||||
|
for(int x = 0; x < image->x; x++){
|
||||||
|
pixel.x = dst_x + x;
|
||||||
|
for(int y = 0; y < image->y; y++){
|
||||||
|
pixel.y = dst_y + y;
|
||||||
|
const int current_pixel_idx = (y * image->x + x) * DESIRED_IMAGE_CHANNELS;
|
||||||
|
|
||||||
|
Uint32 color = SDL_MapSurfaceRGBA(surface,
|
||||||
|
image->pixels[current_pixel_idx + 0],
|
||||||
|
image->pixels[current_pixel_idx + 1],
|
||||||
|
image->pixels[current_pixel_idx + 2],
|
||||||
|
image->pixels[current_pixel_idx + 3]);
|
||||||
|
|
||||||
|
SDL_FillSurfaceRect(surface, &pixel, color);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
int main(int argc, char** argv){
|
||||||
|
if(argc < 2){
|
||||||
|
printf("Usage: %s [image filepath]\n", argv[0]);
|
||||||
|
exit(1);
|
||||||
|
}
|
||||||
|
|
||||||
|
const char* filepath = argv[1];
|
||||||
|
|
||||||
|
if(access(filepath, F_OK) != 0){
|
||||||
|
printf("File does not exist!\n");
|
||||||
|
exit(2);
|
||||||
|
}
|
||||||
|
|
||||||
|
Image image = load_image(filepath);
|
||||||
|
if(image.pixels == NULL){
|
||||||
|
printf("Failed to load image!");
|
||||||
|
exit(3);
|
||||||
|
}
|
||||||
|
|
||||||
|
printf("Dimensions: Width = %d, Height = %d\n", image.x, image.y);
|
||||||
|
|
||||||
|
SDL_Window* window = create_window("SimpleImageViewer", image.x, image.y);
|
||||||
|
if(!window){
|
||||||
|
printf("Failed to create window!");
|
||||||
|
exit(4);
|
||||||
|
}
|
||||||
|
|
||||||
|
SDL_Surface* surface = get_surface_from_window(window);
|
||||||
|
if(!surface){
|
||||||
|
printf("Failed to get surface!");
|
||||||
|
exit(5);
|
||||||
|
}
|
||||||
|
|
||||||
|
draw_image(surface, &image);
|
||||||
|
|
||||||
|
free_image(&image);
|
||||||
|
|
||||||
|
SDL_UpdateWindowSurface(window);
|
||||||
|
|
||||||
|
bool drag_mouse = false;
|
||||||
|
int last_pointer_x = 0;
|
||||||
|
int last_pointer_y = 0;
|
||||||
|
|
||||||
|
SDL_Event event;
|
||||||
|
bool run = true;
|
||||||
|
while(run){
|
||||||
|
while (SDL_PollEvent(&event)) {
|
||||||
|
if (event.type == SDL_EVENT_KEY_UP){
|
||||||
|
switch(event.key.key){
|
||||||
|
case SDLK_ESCAPE: case SDLK_SPACE: case SDLK_RETURN:
|
||||||
|
run = false;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if(event.type == SDL_EVENT_QUIT) run = false;
|
||||||
|
if(event.type == SDL_EVENT_MOUSE_BUTTON_DOWN && event.button.button == SDL_BUTTON_LEFT){
|
||||||
|
drag_mouse = true;
|
||||||
|
last_pointer_x = event.motion.x;
|
||||||
|
last_pointer_y = event.motion.y;
|
||||||
|
}
|
||||||
|
if(event.type == SDL_EVENT_MOUSE_BUTTON_UP && event.button.button == SDL_BUTTON_LEFT) drag_mouse = false;
|
||||||
|
if(event.type == SDL_EVENT_MOUSE_MOTION && drag_mouse){
|
||||||
|
int last_x, last_y;
|
||||||
|
SDL_GetWindowPosition(window, &last_x, &last_y);
|
||||||
|
SDL_SetWindowPosition(window, last_x + (int)event.motion.x - last_pointer_x, last_y + (int)event.motion.y - last_pointer_y);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
SDL_DestroyWindow(window);
|
||||||
|
}
|
||||||
+7988
File diff suppressed because it is too large
Load Diff
Reference in New Issue
Block a user