Исправь в этом коде 2 момента:

    При приближении зума srcRect начинает уменьшаться не сразу. Сделай zoom_speed стартовую скорость, которая будет устанавливаться при начала приближения камеры
    Сделай курсор точкой зума. При зуме srcRect должен уменьшаться вокруг курсора

// mainEditor.c
#include <SDL2/SDL.h>
#include <SDL2/SDL_image.h>
#include <stdio.h>
#include "zoom.h"

#define WINDOW_WIDTH 800
#define WINDOW_HEIGHT 600

int main(int argc, char *argv[])
{
SDL_Window *window = NULL;
SDL_Renderer *renderer = NULL;
SDL_Texture *texture = NULL;
SDL_Event event;
int quit = 0;

int image_width, image_height;

// Initialize SDL
if (SDL_Init(SDL_INIT_VIDEO) < 0)
{
printf("SDL could not initialize! SDL_Error: %s\n", SDL_GetError());
return -1;
}

// Initialize SDL_image
if (!(IMG_Init(IMG_INIT_PNG) & IMG_INIT_PNG))
{
printf("SDL_image could not initialize! SDL_image Error: %s\n", IMG_GetError());
SDL_Quit();
return -1;
}

// Create window
window = SDL_CreateWindow("OpenAge Map Editor",
SDL_WINDOWPOS_CENTERED,
SDL_WINDOWPOS_CENTERED,
WINDOW_WIDTH,
WINDOW_HEIGHT,
SDL_WINDOW_RESIZABLE);

if (window == NULL)
{
printf("Window could not be created! SDL_Error: %s\n", SDL_GetError());
IMG_Quit();
SDL_Quit();
return -1;
}

// Create renderer
renderer = SDL_CreateRenderer(window, -1, SDL_RENDERER_ACCELERATED);
if (renderer == NULL)
{
printf("Renderer could not be created! SDL_Error: %s\n", SDL_GetError());
SDL_DestroyWindow(window);
IMG_Quit();
SDL_Quit();
return -1;
}

// Load image
SDL_Surface *loadedSurface = IMG_Load("./map/world/background.png");
if (loadedSurface == NULL)
{
printf("Unable to load image %s! SDL_image Error: %s\n", "./map/world/background.png", IMG_GetError());
SDL_DestroyRenderer(renderer);
SDL_DestroyWindow(window);
IMG_Quit();
SDL_Quit();
return -1;
}

// Create texture from surface
texture = SDL_CreateTextureFromSurface(renderer, loadedSurface);
if (texture == NULL)
{
printf("Unable to create texture from %s! SDL Error: %s\n", "./map/world/background.png", SDL_GetError());
SDL_FreeSurface(loadedSurface);
SDL_DestroyRenderer(renderer);
SDL_DestroyWindow(window);
IMG_Quit();
SDL_Quit();
return -1; // Добавлено завершение при ошибке
}

image_width = loadedSurface->w;
image_height = loadedSurface->h;

SDL_FreeSurface(loadedSurface);

// Get initial window size
int window_width, window_height;
SDL_GetWindowSize(window, &window_width, &window_height);

// Initialize zoom and camera
init_zoom(image_width, image_height, window_width, window_height);

// Main loop
while (!quit)
{
// Event handling
while (SDL_PollEvent(&event))
{
switch (event.type)
{
case SDL_QUIT:
quit = 1;
break;

    case SDL_WINDOWEVENT:
        if (event.window.event == SDL_WINDOWEVENT_RESIZED)
        {
            // Update window size
            SDL_GetWindowSize(window, &window_width, &window_height);
            set_window_size(window_width, window_height);
        }
        break;

    case SDL_MOUSEBUTTONDOWN:
        if (event.button.button == SDL_BUTTON_LEFT)
        {
            // Start dragging
            start_camera_drag(event.button.x, event.button.y);
        }
        break;

    case SDL_MOUSEBUTTONUP:
        if (event.button.button == SDL_BUTTON_LEFT)
        {
            // Stop dragging
            stop_camera_drag();
        }
        break;

    case SDL_MOUSEMOTION:
        // Update camera dragging
        update_camera_drag(event.motion.x, event.motion.y);
        break;

    case SDL_MOUSEWHEEL:
        // Zoom in and out
        if (event.wheel.y > 0)
        {
            zoom_in();
        }
        else if (event.wheel.y < 0)
        {
            zoom_out();
        }
        break;

    default:
        break;
    }
}

// Update zoom level
update_zoom();

// Update camera position
update_camera(); // Эта функция может быть оставлена для будущего использования

// Get the source rectangle for rendering
SDL_Rect src_rect = get_source_rect();

// Set the destination rectangle (where to render the image in the window)
SDL_Rect dst_rect;
dst_rect.x = 0;
dst_rect.y = 0;
dst_rect.w = window_width;
dst_rect.h = window_height;

// Clear renderer
SDL_SetRenderDrawColor(renderer, 0, 0, 0, 255); // Black background
SDL_RenderClear(renderer);

// Render the texture
SDL_RenderCopy(renderer, texture, &src_rect, &dst_rect);

// Update screen
SDL_RenderPresent(renderer);

// Delay to control frame rate
SDL_Delay(16); // Approximately 60 frames per second

}

// Clean up
SDL_DestroyTexture(texture);
SDL_DestroyRenderer(renderer);
SDL_DestroyWindow(window);
IMG_Quit();
SDL_Quit();

return 0;

}

// zoom.c
#include "zoom.h"

static float zoom_level = 1.0f;
static float zoom_target = 1.0f;
static const float zoom_speed = 0.1f;
static const float zoom_factor = 1.1f; // Zoom increment factor

// Image and window dimensions
static int image_width = 0;
static int image_height = 0;
static int window_width = 0;
static int window_height = 0;

// Camera properties
static float camera_x = 0.0f;
static float camera_y = 0.0f;

static int dragging = 0;
static int prev_mouse_x = 0;
static int prev_mouse_y = 0;

// Initialize zoom and camera settings
void init_zoom(int img_width, int img_height, int win_width, int win_height)
{
zoom_level = 1.0f;
zoom_target = 1.0f;
image_width = img_width;
image_height = img_height;
window_width = win_width;
window_height = win_height;
camera_x = 0.0f;
camera_y = 0.0f;
}

// Zoom functions
void zoom_in()
{
zoom_target *= zoom_factor;
}

void zoom_out()
{
zoom_target /= zoom_factor;
}

void update_zoom()
{
// Smoothly interpolate towards the target zoom level
zoom_level += (zoom_target - zoom_level) * zoom_speed;

// Clamp zoom level
if (zoom_level < 0.1f)
{
zoom_level = 0.1f;
zoom_target = 0.1f;
}
if (zoom_level > 10.0f)
{
zoom_level = 10.0f;
zoom_target = 10.0f;
}

}

// Camera drag functions
void start_camera_drag(int mouse_x, int mouse_y)
{
dragging = 1;
prev_mouse_x = mouse_x;
prev_mouse_y = mouse_y;
}

void stop_camera_drag()
{
dragging = 0;
}

void update_camera_drag(int mouse_x, int mouse_y)
{
if (dragging)
{
// Calculate the difference in mouse movement
int delta_x = mouse_x - prev_mouse_x;
int delta_y = mouse_y - prev_mouse_y;

// Update the camera position inversely to the mouse movement
camera_x -= delta_x / zoom_level;
camera_y -= delta_y / zoom_level;

// Update previous mouse position
prev_mouse_x = mouse_x;
prev_mouse_y = mouse_y;

}

}

// Update camera position and enforce boundaries
void update_camera()
{
// Обновление позиции камеры перенесено в get_source_rect()
// Эта функция может остаться пустой или использоваться для будущих обновлений
}

// Window resize handling
void set_window_size(int win_width, int win_height)
{
window_width = win_width;
window_height = win_height;
}

// Getter functions
float get_zoom_level()
{
return zoom_level;
}

SDL_Rect get_source_rect()
{
SDL_Rect src_rect;

// Calculate the aspect ratio of the window
float window_aspect_ratio = (float)window_width / (float)window_height;

// Calculate the initial visible width and height based on zoom level
float visible_width = window_width / zoom_level;
float visible_height = window_height / zoom_level;

// Adjust visible area to maintain aspect ratio
float adjusted_width = visible_width;
float adjusted_height = visible_height;

float current_aspect_ratio = visible_width / visible_height;

if (current_aspect_ratio > window_aspect_ratio)
{
// Width is too big compared to height, adjust width
adjusted_width = visible_height * window_aspect_ratio;
}
else if (current_aspect_ratio < window_aspect_ratio)
{
// Height is too big compared to width, adjust height
adjusted_height = visible_width / window_aspect_ratio;
}

visible_width = adjusted_width;
visible_height = adjusted_height;

// Ensure visible dimensions do not exceed image dimensions
if (visible_width > image_width)
{
visible_width = (float)image_width;
visible_height = visible_width / window_aspect_ratio;
}

if (visible_height > image_height)
{
visible_height = (float)image_height;
visible_width = visible_height * window_aspect_ratio;
}

// Adjust camera position to ensure src_rect is within image boundaries
float max_camera_x = image_width - visible_width;
float max_camera_y = image_height - visible_height;

if (camera_x < 0)
camera_x = 0;
if (camera_x > max_camera_x)
camera_x = max_camera_x;

if (camera_y < 0)
camera_y = 0;
if (camera_y > max_camera_y)
camera_y = max_camera_y;

src_rect.x = (int)camera_x;
src_rect.y = (int)camera_y;
src_rect.w = (int)visible_width;
src_rect.h = (int)visible_height;

return src_rect;

}

// zoom.h
#ifndef ZOOM_H
#define ZOOM_H

#include <SDL2/SDL.h>

// Initialize zoom and camera settings
void init_zoom(int image_width, int image_height, int window_width, int window_height);

// Zoom controls
void zoom_in();
void zoom_out();
void update_zoom();

// Camera controls
void start_camera_drag(int mouse_x, int mouse_y);
void stop_camera_drag();
void update_camera_drag(int mouse_x, int mouse_y);
void update_camera(); // Call this each frame

// Window resize handling
void set_window_size(int window_width, int window_height);

// Getters
float get_zoom_level();
SDL_Rect get_source_rect();

#endif // ZOOM_H