diff --git a/.vscode/settings.json b/.vscode/settings.json new file mode 100644 index 0000000..4f0087b --- /dev/null +++ b/.vscode/settings.json @@ -0,0 +1,6 @@ +{ + "files.associations": { + "*.py": "python", + "stdio.h": "c" + } +} \ No newline at end of file diff --git a/C/imageViewer/lint.sh b/C/imageViewer/lint.sh index c3a3750..8a095d1 100755 --- a/C/imageViewer/lint.sh +++ b/C/imageViewer/lint.sh @@ -86,8 +86,8 @@ run_clang_tidy() { run_cppcheck() { print_step "Running cppcheck analysis..." - cppcheck --enable=all --suppress=missingIncludeSystem --suppress=unusedFunction \ - --suppress=constParameter --quiet --std=c99 main.c || { + cppcheck --enable=all --check-level=exhaustive --suppress=missingIncludeSystem \ + --quiet --std=c23 main.c || { print_warning "cppcheck found issues (see output above)" } diff --git a/C/imageViewer/main.c b/C/imageViewer/main.c index 356763d..898799f 100644 --- a/C/imageViewer/main.c +++ b/C/imageViewer/main.c @@ -1,28 +1,35 @@ +#include +#include +#include #include #include #include -#include -#include #include -#include -#include +#include #define WINDOW_WIDTH 800 #define WINDOW_HEIGHT 600 #define MAX_PATH_LEN 512 #define MAX_FILES 1000 +// Auto-navigation and rendering constants +#define AUTO_NAV_INTERVAL_MS 100 +#define BACKGROUND_COLOR_R 32 +#define BACKGROUND_COLOR_G 32 +#define BACKGROUND_COLOR_B 32 +#define BACKGROUND_COLOR_A 255 + typedef struct { - char** files; + char **files; int count; int current_index; char base_dir[MAX_PATH_LEN]; } FileList; typedef struct { - SDL_Window* window; - SDL_Renderer* renderer; - SDL_Texture* texture; + SDL_Window *window; + SDL_Renderer *renderer; + SDL_Texture *texture; char current_file[MAX_PATH_LEN]; int image_width; int image_height; @@ -33,7 +40,7 @@ typedef struct { int last_mouse_x; int last_mouse_y; FileList file_list; - + // Auto-navigation state int left_key_held; int right_key_held; @@ -42,61 +49,67 @@ typedef struct { } ImageViewer; // Function declarations -static int is_image_file(const char* filename); -static int init_file_list(FileList* list, const char* path); -static void cleanup_file_list(FileList* list); -static char* get_current_file_path(const FileList* list); -static int navigate_to_file(FileList* list, const char* target_filename); -static int load_current_image(ImageViewer* viewer); -static int navigate_next_image(ImageViewer* viewer); -static int navigate_prev_image(ImageViewer* viewer); -static void print_current_image_info(const ImageViewer* viewer); -static void handle_auto_navigation(ImageViewer* viewer); +static int is_image_file(const char *filename); +static int init_file_list(FileList *list, const char *path); +static void cleanup_file_list(FileList *list); +static char *get_current_file_path(const FileList *list); +static int load_current_image(ImageViewer *viewer); +static int navigate_next_image(ImageViewer *viewer); +static int navigate_prev_image(ImageViewer *viewer); +static void print_current_image_info(const ImageViewer *viewer); +static void handle_auto_navigation(ImageViewer *viewer); // Safe memory copy wrapper to address static analyzer warnings -static int safe_copy_memory(void* dest, size_t dest_size, const void* src, size_t src_len) { +static int safe_copy_memory(void *dest, size_t dest_size, const void *src, size_t src_len) { if (!dest || !src || dest_size == 0 || src_len == 0) { return 0; // Invalid parameters } - + if (src_len > dest_size) { return 0; // Source too large for destination } - - memcpy(dest, src, src_len); // NOLINT(clang-analyzer-security.insecureAPI.DeprecatedOrUnsafeBufferHandling) - return 1; // Success + + memcpy(dest, + src, + src_len); // NOLINT(clang-analyzer-security.insecureAPI.DeprecatedOrUnsafeBufferHandling) + return 1; // Success } // Safe string copy with automatic null termination -static int safe_copy_string(char* dest, size_t dest_size, const char* src, size_t src_len) { +static int safe_copy_string(char *dest, size_t dest_size, const char *src, size_t src_len) { if (!dest || !src || dest_size <= 1) { return 0; // Invalid parameters or dest too small for null terminator } - + size_t copy_len = (src_len < dest_size - 1) ? src_len : dest_size - 1; if (!safe_copy_memory(dest, dest_size, src, copy_len)) { return 0; } - + dest[copy_len] = '\0'; return 1; // Success } // Safe path formatting wrapper to address static analyzer warnings -static int safe_format_path(char* dest, size_t dest_size, const char* dir, const char* filename) { +static int safe_format_path(char *dest, size_t dest_size, const char *dir, const char *filename) { if (!dest || !dir || !filename || dest_size == 0) { return 0; // Invalid parameters } - - int ret = snprintf(dest, dest_size, "%s/%s", dir, filename); // NOLINT(clang-analyzer-security.insecureAPI.DeprecatedOrUnsafeBufferHandling) + + int ret = snprintf( + dest, + dest_size, + "%s/%s", + dir, + filename); // NOLINT(clang-analyzer-security.insecureAPI.DeprecatedOrUnsafeBufferHandling) if (ret < 0 || (size_t)ret >= dest_size) { return 0; // Formatting failed or path too long } - + return 1; // Success } -static int init_viewer(ImageViewer* viewer) { +static int init_viewer(ImageViewer *viewer) { if (SDL_Init(SDL_INIT_VIDEO) < 0) { printf("SDL could not initialize! SDL_Error: %s\n", SDL_GetError()); return 0; @@ -115,7 +128,7 @@ static int init_viewer(ImageViewer* viewer) { WINDOW_WIDTH, WINDOW_HEIGHT, SDL_WINDOW_SHOWN | SDL_WINDOW_RESIZABLE); - + if (!viewer->window) { printf("Window could not be created! SDL_Error: %s\n", SDL_GetError()); IMG_Quit(); @@ -140,29 +153,29 @@ static int init_viewer(ImageViewer* viewer) { viewer->dragging = 0; viewer->image_width = 0; viewer->image_height = 0; - + // Initialize file list viewer->file_list.files = NULL; viewer->file_list.count = 0; viewer->file_list.current_index = 0; viewer->file_list.base_dir[0] = '\0'; - + // Initialize auto-navigation state viewer->left_key_held = 0; viewer->right_key_held = 0; viewer->last_auto_nav_time = 0; - viewer->auto_nav_interval = 100; + viewer->auto_nav_interval = AUTO_NAV_INTERVAL_MS; return 1; } -static int load_image(ImageViewer* viewer, const char* filename) { +static int load_image(ImageViewer *viewer, const char *filename) { if (viewer->texture) { SDL_DestroyTexture(viewer->texture); viewer->texture = NULL; } - SDL_Surface* surface = IMG_Load(filename); + SDL_Surface *surface = IMG_Load(filename); if (!surface) { printf("Unable to load image %s! SDL_image Error: %s\n", filename, IMG_GetError()); return 0; @@ -192,11 +205,11 @@ static int load_image(ImageViewer* viewer, const char* filename) { int window_w, window_h; SDL_GetWindowSize(viewer->window, &window_w, &window_h); - + float scale_x = (float)window_w / viewer->image_width; float scale_y = (float)window_h / viewer->image_height; float auto_scale = (scale_x < scale_y) ? scale_x : scale_y; - + // Only scale down if image is larger than window, never scale up if (auto_scale < 1.0f) { viewer->zoom_factor = auto_scale; @@ -206,8 +219,8 @@ static int load_image(ImageViewer* viewer, const char* filename) { return 1; } -static void render_image(ImageViewer* viewer) { - SDL_SetRenderDrawColor(viewer->renderer, 32, 32, 32, 255); +static void render_image(ImageViewer *viewer) { + SDL_SetRenderDrawColor(viewer->renderer, BACKGROUND_COLOR_R, BACKGROUND_COLOR_G, BACKGROUND_COLOR_B, BACKGROUND_COLOR_A); SDL_RenderClear(viewer->renderer); if (!viewer->texture) { @@ -230,23 +243,27 @@ static void render_image(ImageViewer* viewer) { SDL_RenderPresent(viewer->renderer); } -static void handle_zoom(ImageViewer* viewer, float zoom_delta, int mouse_x, int mouse_y) { +static void handle_zoom(ImageViewer *viewer, float zoom_delta, int mouse_x, int mouse_y) { float old_zoom = viewer->zoom_factor; viewer->zoom_factor += zoom_delta; - - if (viewer->zoom_factor < 0.1f) viewer->zoom_factor = 0.1f; - if (viewer->zoom_factor > 10.0f) viewer->zoom_factor = 10.0f; + + if (viewer->zoom_factor < 0.1f) + viewer->zoom_factor = 0.1f; + if (viewer->zoom_factor > 10.0f) + viewer->zoom_factor = 10.0f; float zoom_ratio = viewer->zoom_factor / old_zoom; - + int window_w, window_h; SDL_GetWindowSize(viewer->window, &window_w, &window_h); - + int center_x = window_w / 2; int center_y = window_h / 2; - - viewer->offset_x = (viewer->offset_x - (mouse_x - center_x)) * zoom_ratio + (mouse_x - center_x); - viewer->offset_y = (viewer->offset_y - (mouse_y - center_y)) * zoom_ratio + (mouse_y - center_y); + + viewer->offset_x = + (viewer->offset_x - (mouse_x - center_x)) * zoom_ratio + (mouse_x - center_x); + viewer->offset_y = + (viewer->offset_y - (mouse_y - center_y)) * zoom_ratio + (mouse_y - center_y); } static void print_help() { @@ -262,7 +279,7 @@ static void print_help() { printf("===============================\n\n"); } -static void cleanup_viewer(ImageViewer* viewer) { +static void cleanup_viewer(ImageViewer *viewer) { if (viewer->texture) { SDL_DestroyTexture(viewer->texture); } @@ -277,10 +294,11 @@ static void cleanup_viewer(ImageViewer* viewer) { SDL_Quit(); } -static int is_image_file(const char* filename) { - const char* ext = strrchr(filename, '.'); - if (!ext) return 0; - +static int is_image_file(const char *filename) { + const char *ext = strrchr(filename, '.'); + if (!ext) + return 0; + ext++; // Skip the dot return (strcasecmp(ext, "jpg") == 0 || strcasecmp(ext, "jpeg") == 0 || strcasecmp(ext, "png") == 0 || strcasecmp(ext, "bmp") == 0 || @@ -288,34 +306,34 @@ static int is_image_file(const char* filename) { strcasecmp(ext, "tiff") == 0 || strcasecmp(ext, "webp") == 0); } -static int init_file_list(FileList* list, const char* path) { +static int init_file_list(FileList *list, const char *path) { struct stat path_stat; list->files = NULL; list->count = 0; list->current_index = 0; - + if (stat(path, &path_stat) != 0) { printf("Error: Cannot access path %s\n", path); return 0; } - + if (S_ISDIR(path_stat.st_mode)) { // It's a directory - scan for image files - DIR* dir = opendir(path); + DIR *dir = opendir(path); if (!dir) { printf("Error: Cannot open directory %s\n", path); return 0; } - + size_t path_len = strlen(path); if (!safe_copy_string(list->base_dir, MAX_PATH_LEN, path, path_len)) { printf("Error: Path too long\n"); closedir(dir); return 0; } - + // First pass: count image files - struct dirent* entry; + const struct dirent *entry; while ((entry = readdir(dir)) != NULL) { if (entry->d_name[0] != '.' && is_image_file(entry->d_name)) { // Build full path and check if it's a regular file @@ -329,21 +347,21 @@ static int init_file_list(FileList* list, const char* path) { } } } - + if (list->count == 0) { printf("No image files found in directory %s\n", path); closedir(dir); return 0; } - + // Allocate memory for file list - list->files = malloc(list->count * sizeof(char*)); + list->files = malloc(list->count * sizeof(char *)); if (!list->files) { printf("Error: Memory allocation failed\n"); closedir(dir); return 0; } - + // Second pass: store filenames rewinddir(dir); int index = 0; @@ -359,7 +377,8 @@ static int init_file_list(FileList* list, const char* path) { list->files[index] = malloc(strlen(entry->d_name) + 1); if (list->files[index]) { size_t name_len = strlen(entry->d_name); - if (safe_copy_string(list->files[index], name_len + 1, entry->d_name, name_len)) { + if (safe_copy_string( + list->files[index], name_len + 1, entry->d_name, name_len)) { index++; } else { free(list->files[index]); @@ -370,9 +389,9 @@ static int init_file_list(FileList* list, const char* path) { } } list->count = index; // Update count to actual stored files - + closedir(dir); - + // Sort files alphabetically by filename without extension, shorter names first for (int i = 0; i < list->count - 1; i++) { for (int j = 0; j < list->count - i - 1; j++) { @@ -380,22 +399,24 @@ static int init_file_list(FileList* list, const char* path) { char name1[MAX_PATH_LEN], name2[MAX_PATH_LEN]; size_t len1 = strlen(list->files[j]); size_t len2 = strlen(list->files[j + 1]); - + if (!safe_copy_string(name1, MAX_PATH_LEN, list->files[j], len1) || !safe_copy_string(name2, MAX_PATH_LEN, list->files[j + 1], len2)) { continue; // Skip if copy fails } - - char* dot1 = strrchr(name1, '.'); - char* dot2 = strrchr(name2, '.'); - if (dot1) *dot1 = '\0'; - if (dot2) *dot2 = '\0'; - + + char *dot1 = strrchr(name1, '.'); + char *dot2 = strrchr(name2, '.'); + if (dot1) + *dot1 = '\0'; + if (dot2) + *dot2 = '\0'; + // Custom comparison: shorter names first, then alphabetical int should_swap = 0; int name1_len = strlen(name1); int name2_len = strlen(name2); - + if (name1_len != name2_len) { // Different lengths - shorter comes first should_swap = (name1_len > name2_len); @@ -403,28 +424,28 @@ static int init_file_list(FileList* list, const char* path) { // Same length - alphabetical order should_swap = (strcmp(name1, name2) > 0); } - + if (should_swap) { - char* temp = list->files[j]; + char *temp = list->files[j]; list->files[j] = list->files[j + 1]; list->files[j + 1] = temp; } } } - + printf("Found %d image files in directory\n", list->count); - + } else if (S_ISREG(path_stat.st_mode)) { // It's a single file - scan its directory for all images if (!is_image_file(path)) { printf("Error: %s is not a supported image file\n", path); return 0; } - + // Extract directory and filename - char* last_slash = strrchr(path, '/'); - const char* target_filename; - + char *last_slash = strrchr(path, '/'); + const char *target_filename; + if (last_slash) { size_t dir_len = last_slash - path; if (!safe_copy_string(list->base_dir, MAX_PATH_LEN, path, dir_len)) { @@ -439,22 +460,23 @@ static int init_file_list(FileList* list, const char* path) { } target_filename = path; } - + // Now scan the directory for all image files - DIR* dir = opendir(list->base_dir); + DIR *dir = opendir(list->base_dir); if (!dir) { printf("Error: Cannot open directory %s\n", list->base_dir); return 0; } - + // First pass: count image files in directory - struct dirent* entry; + const struct dirent *entry; list->count = 0; while ((entry = readdir(dir)) != NULL) { if (entry->d_name[0] != '.' && is_image_file(entry->d_name)) { // Build full path and check if it's a regular file char full_path[MAX_PATH_LEN * 2]; - if (!safe_format_path(full_path, sizeof(full_path), list->base_dir, entry->d_name)) { + if (!safe_format_path( + full_path, sizeof(full_path), list->base_dir, entry->d_name)) { continue; // Skip if path formatting fails or path too long } struct stat file_stat; @@ -463,21 +485,21 @@ static int init_file_list(FileList* list, const char* path) { } } } - + if (list->count == 0) { printf("No image files found in directory %s\n", list->base_dir); closedir(dir); return 0; } - + // Allocate memory for file list - list->files = malloc(list->count * sizeof(char*)); + list->files = malloc(list->count * sizeof(char *)); if (!list->files) { printf("Error: Memory allocation failed\n"); closedir(dir); return 0; } - + // Second pass: store filenames rewinddir(dir); int index = 0; @@ -485,7 +507,8 @@ static int init_file_list(FileList* list, const char* path) { if (entry->d_name[0] != '.' && is_image_file(entry->d_name)) { // Build full path and check if it's a regular file char full_path[MAX_PATH_LEN * 2]; - if (!safe_format_path(full_path, sizeof(full_path), list->base_dir, entry->d_name)) { + if (!safe_format_path( + full_path, sizeof(full_path), list->base_dir, entry->d_name)) { continue; // Skip if path formatting fails or path too long } struct stat file_stat; @@ -493,7 +516,8 @@ static int init_file_list(FileList* list, const char* path) { list->files[index] = malloc(strlen(entry->d_name) + 1); if (list->files[index]) { size_t name_len = strlen(entry->d_name); - if (safe_copy_string(list->files[index], name_len + 1, entry->d_name, name_len)) { + if (safe_copy_string( + list->files[index], name_len + 1, entry->d_name, name_len)) { index++; } else { free(list->files[index]); @@ -504,9 +528,9 @@ static int init_file_list(FileList* list, const char* path) { } } list->count = index; // Update count to actual stored files - + closedir(dir); - + // Sort files alphabetically by filename without extension, shorter names first for (int i = 0; i < list->count - 1; i++) { for (int j = 0; j < list->count - i - 1; j++) { @@ -514,22 +538,24 @@ static int init_file_list(FileList* list, const char* path) { char name1[MAX_PATH_LEN], name2[MAX_PATH_LEN]; size_t len1 = strlen(list->files[j]); size_t len2 = strlen(list->files[j + 1]); - + if (!safe_copy_string(name1, MAX_PATH_LEN, list->files[j], len1) || !safe_copy_string(name2, MAX_PATH_LEN, list->files[j + 1], len2)) { continue; // Skip if copy fails } - - char* dot1 = strrchr(name1, '.'); - char* dot2 = strrchr(name2, '.'); - if (dot1) *dot1 = '\0'; - if (dot2) *dot2 = '\0'; - + + char *dot1 = strrchr(name1, '.'); + char *dot2 = strrchr(name2, '.'); + if (dot1) + *dot1 = '\0'; + if (dot2) + *dot2 = '\0'; + // Custom comparison: shorter names first, then alphabetical int should_swap = 0; int name1_len = strlen(name1); int name2_len = strlen(name2); - + if (name1_len != name2_len) { // Different lengths - shorter comes first should_swap = (name1_len > name2_len); @@ -537,15 +563,15 @@ static int init_file_list(FileList* list, const char* path) { // Same length - alphabetical order should_swap = (strcmp(name1, name2) > 0); } - + if (should_swap) { - char* temp = list->files[j]; + char *temp = list->files[j]; list->files[j] = list->files[j + 1]; list->files[j + 1] = temp; } } } - + // Find the target file in the sorted list and set current_index for (int i = 0; i < list->count; i++) { if (strcmp(list->files[i], target_filename) == 0) { @@ -553,18 +579,19 @@ static int init_file_list(FileList* list, const char* path) { break; } } - - printf("Found %d image files in directory, starting with: %s\n", list->count, target_filename); - + + printf( + "Found %d image files in directory, starting with: %s\n", list->count, target_filename); + } else { printf("Error: %s is neither a file nor a directory\n", path); return 0; } - + return 1; } -static void cleanup_file_list(FileList* list) { +static void cleanup_file_list(FileList *list) { if (list->files) { for (int i = 0; i < list->count; i++) { if (list->files[i]) { @@ -578,58 +605,61 @@ static void cleanup_file_list(FileList* list) { list->current_index = 0; } -static char* get_current_file_path(const FileList* list) { +static char *get_current_file_path(const FileList *list) { if (!list->files || list->current_index < 0 || list->current_index >= list->count) { return NULL; } - + static char full_path[MAX_PATH_LEN * 2]; - if (!safe_format_path(full_path, sizeof(full_path), list->base_dir, list->files[list->current_index])) { + if (!safe_format_path( + full_path, sizeof(full_path), list->base_dir, list->files[list->current_index])) { return NULL; // Path formatting failed or path too long } return full_path; } - -static int load_current_image(ImageViewer* viewer) { - char* file_path = get_current_file_path(&viewer->file_list); +static int load_current_image(ImageViewer *viewer) { + const char *file_path = get_current_file_path(&viewer->file_list); if (!file_path) { printf("No current file to load\n"); return 0; } - + return load_image(viewer, file_path); } -static int navigate_next_image(ImageViewer* viewer) { - if (viewer->file_list.count <= 1) return 0; - - viewer->file_list.current_index = (viewer->file_list.current_index + 1) % viewer->file_list.count; +static int navigate_next_image(ImageViewer *viewer) { + if (viewer->file_list.count <= 1) + return 0; + + viewer->file_list.current_index = + (viewer->file_list.current_index + 1) % viewer->file_list.count; return load_current_image(viewer); } -static int navigate_prev_image(ImageViewer* viewer) { - if (viewer->file_list.count <= 1) return 0; - - viewer->file_list.current_index = (viewer->file_list.current_index - 1 + viewer->file_list.count) % viewer->file_list.count; +static int navigate_prev_image(ImageViewer *viewer) { + if (viewer->file_list.count <= 1) + return 0; + + viewer->file_list.current_index = + (viewer->file_list.current_index - 1 + viewer->file_list.count) % viewer->file_list.count; return load_current_image(viewer); } -static void print_current_image_info(const ImageViewer* viewer) { +static void print_current_image_info(const ImageViewer *viewer) { if (viewer->file_list.count > 1) { - printf("Image %d/%d: %s\n", - viewer->file_list.current_index + 1, + printf("Image %d/%d: %s\n", + viewer->file_list.current_index + 1, viewer->file_list.count, viewer->file_list.files[viewer->file_list.current_index]); } } -static void handle_auto_navigation(ImageViewer* viewer) { +static void handle_auto_navigation(ImageViewer *viewer) { Uint32 current_time = SDL_GetTicks(); - - if ((viewer->left_key_held || viewer->right_key_held) && + + if ((viewer->left_key_held || viewer->right_key_held) && (current_time - viewer->last_auto_nav_time >= viewer->auto_nav_interval)) { - if (viewer->left_key_held) { if (navigate_prev_image(viewer)) { print_current_image_info(viewer); @@ -639,12 +669,12 @@ static void handle_auto_navigation(ImageViewer* viewer) { print_current_image_info(viewer); } } - + viewer->last_auto_nav_time = current_time; } } -int main(int argc, char* argv[]) { +int main(int argc, char *argv[]) { if (argc != 2) { printf("Usage: %s \n", argv[0]); printf("Supported formats: JPG, JPEG, PNG, BMP, GIF, TIF, WEBP\n"); @@ -652,7 +682,7 @@ int main(int argc, char* argv[]) { } ImageViewer viewer; - + if (!init_viewer(&viewer)) { printf("Failed to initialize image viewer!\n"); return 1; @@ -697,28 +727,26 @@ int main(int argc, char* argv[]) { printf("Reset view\n"); break; - case SDLK_f: - { - int window_w, window_h; - SDL_GetWindowSize(viewer.window, &window_w, &window_h); - - float scale_x = (float)window_w / viewer.image_width; - float scale_y = (float)window_h / viewer.image_height; - viewer.zoom_factor = (scale_x < scale_y) ? scale_x : scale_y; - viewer.offset_x = 0; - viewer.offset_y = 0; - printf("Fit to window (zoom: %.2f)\n", viewer.zoom_factor); - } - break; + case SDLK_f: { + int window_w, window_h; + SDL_GetWindowSize(viewer.window, &window_w, &window_h); + + float scale_x = (float)window_w / viewer.image_width; + float scale_y = (float)window_h / viewer.image_height; + viewer.zoom_factor = (scale_x < scale_y) ? scale_x : scale_y; + viewer.offset_x = 0; + viewer.offset_y = 0; + printf("Fit to window (zoom: %.2f)\n", viewer.zoom_factor); + } break; case SDLK_PLUS: case SDLK_EQUALS: - handle_zoom(&viewer, 0.1f, WINDOW_WIDTH/2, WINDOW_HEIGHT/2); + handle_zoom(&viewer, 0.1f, WINDOW_WIDTH / 2, WINDOW_HEIGHT / 2); printf("Zoom: %.2f\n", viewer.zoom_factor); break; case SDLK_MINUS: - handle_zoom(&viewer, -0.1f, WINDOW_WIDTH/2, WINDOW_HEIGHT/2); + handle_zoom(&viewer, -0.1f, WINDOW_WIDTH / 2, WINDOW_HEIGHT / 2); printf("Zoom: %.2f\n", viewer.zoom_factor); break; @@ -762,15 +790,13 @@ int main(int argc, char* argv[]) { } break; - case SDL_MOUSEWHEEL: - { - int mouse_x, mouse_y; - SDL_GetMouseState(&mouse_x, &mouse_y); - float zoom_delta = e.wheel.y * 0.1f; - handle_zoom(&viewer, zoom_delta, mouse_x, mouse_y); - printf("Zoom: %.2f\n", viewer.zoom_factor); - } - break; + case SDL_MOUSEWHEEL: { + int mouse_x, mouse_y; + SDL_GetMouseState(&mouse_x, &mouse_y); + float zoom_delta = e.wheel.y * 0.1f; + handle_zoom(&viewer, zoom_delta, mouse_x, mouse_y); + printf("Zoom: %.2f\n", viewer.zoom_factor); + } break; case SDL_MOUSEBUTTONDOWN: if (e.button.button == SDL_BUTTON_LEFT) { @@ -790,10 +816,10 @@ int main(int argc, char* argv[]) { if (viewer.dragging) { int dx = e.motion.x - viewer.last_mouse_x; int dy = e.motion.y - viewer.last_mouse_y; - + viewer.offset_x += dx; viewer.offset_y += dy; - + viewer.last_mouse_x = e.motion.x; viewer.last_mouse_y = e.motion.y; } @@ -802,26 +828,26 @@ int main(int argc, char* argv[]) { case SDL_WINDOWEVENT: if (e.window.event == SDL_WINDOWEVENT_RESIZED) { printf("Window resized to %dx%d\n", e.window.data1, e.window.data2); - + // Recalculate auto-scaling for new window size int window_w = e.window.data1; int window_h = e.window.data2; - + float scale_x = (float)window_w / viewer.image_width; float scale_y = (float)window_h / viewer.image_height; float auto_scale = (scale_x < scale_y) ? scale_x : scale_y; - + // Only scale down if image is larger than window, never scale up if (auto_scale < 1.0f) { viewer.zoom_factor = auto_scale; } else { viewer.zoom_factor = 1.0f; } - + // Reset offset to center the image viewer.offset_x = 0; viewer.offset_y = 0; - + printf("Auto-scaled to zoom: %.2f\n", viewer.zoom_factor); } break;