#define STB_IMAGE_RESIZE_IMPLEMENTATION #include "logo_scaler.h" #include // Para SDL_GetError #include // Para SDL_Log #include // Para SDL_PixelFormat #include // Para SDL_CreateTexture #include // Para SDL_CreateSurfaceFrom #include // Para SDL_GetDisplays #include // Para free() #include // Para std::cout #include "external/stb_image.h" // Para stbi_load, stbi_image_free #include "external/stb_image_resize2.h" // Para stbir_resize_uint8_srgb // ============================================================================ // Detectar resolución nativa del monitor principal // ============================================================================ bool LogoScaler::detectNativeResolution(int& native_width, int& native_height) { int num_displays = 0; SDL_DisplayID* displays = SDL_GetDisplays(&num_displays); if (displays == nullptr || num_displays == 0) { SDL_Log("Error al obtener displays: %s", SDL_GetError()); return false; } // Obtener resolución del display principal (displays[0]) const auto* dm = SDL_GetCurrentDisplayMode(displays[0]); if (dm == nullptr) { SDL_Log("Error al obtener modo del display: %s", SDL_GetError()); SDL_free(displays); return false; } native_width = dm->w; native_height = dm->h; SDL_free(displays); std::cout << "Resolución nativa detectada: " << native_width << "x" << native_height << std::endl; return true; } // ============================================================================ // Cargar PNG y escalar al tamaño especificado // ============================================================================ unsigned char* LogoScaler::loadAndScale(const std::string& path, int target_width, int target_height, int& out_width, int& out_height) { // 1. Cargar imagen original con stb_image int orig_width, orig_height, orig_channels; unsigned char* orig_data = stbi_load(path.c_str(), &orig_width, &orig_height, &orig_channels, STBI_rgb_alpha); if (orig_data == nullptr) { SDL_Log("Error al cargar imagen %s: %s", path.c_str(), stbi_failure_reason()); return nullptr; } std::cout << "Imagen cargada: " << path << " (" << orig_width << "x" << orig_height << ")" << std::endl; // 2. Calcular tamaño final manteniendo aspect ratio // El alto está fijado por target_height (APPLOGO_HEIGHT_PERCENT) // Calcular ancho proporcional al aspect ratio original float aspect_ratio = static_cast(orig_width) / static_cast(orig_height); out_width = static_cast(target_height * aspect_ratio); out_height = target_height; std::cout << " Escalando a: " << out_width << "x" << out_height << std::endl; // 3. Alocar buffer para imagen escalada (RGBA = 4 bytes por píxel) unsigned char* scaled_data = static_cast(malloc(out_width * out_height * 4)); if (scaled_data == nullptr) { SDL_Log("Error al alocar memoria para imagen escalada"); stbi_image_free(orig_data); return nullptr; } // 4. Escalar con stb_image_resize2 (algoritmo Mitchell, espacio sRGB) // La función devuelve el puntero de salida, o nullptr si falla unsigned char* result = stbir_resize_uint8_srgb( orig_data, orig_width, orig_height, 0, // Input scaled_data, out_width, out_height, 0, // Output STBIR_RGBA // Formato píxel ); // Liberar imagen original (ya no la necesitamos) stbi_image_free(orig_data); if (result == nullptr) { SDL_Log("Error al escalar imagen"); free(scaled_data); return nullptr; } std::cout << " Escalado completado correctamente" << std::endl; return scaled_data; } // ============================================================================ // Crear textura SDL desde buffer RGBA // ============================================================================ SDL_Texture* LogoScaler::createTextureFromBuffer(SDL_Renderer* renderer, unsigned char* data, int width, int height) { if (renderer == nullptr || data == nullptr || width <= 0 || height <= 0) { SDL_Log("Parámetros inválidos para createTextureFromBuffer"); return nullptr; } // 1. Crear surface SDL desde buffer RGBA int pitch = width * 4; // 4 bytes por píxel (RGBA) SDL_PixelFormat pixel_format = SDL_PIXELFORMAT_RGBA32; SDL_Surface* surface = SDL_CreateSurfaceFrom( width, height, pixel_format, data, pitch ); if (surface == nullptr) { SDL_Log("Error al crear surface: %s", SDL_GetError()); return nullptr; } // 2. Crear textura desde surface SDL_Texture* texture = SDL_CreateTextureFromSurface(renderer, surface); if (texture == nullptr) { SDL_Log("Error al crear textura: %s", SDL_GetError()); SDL_DestroySurface(surface); return nullptr; } // 3. Liberar surface (la textura ya tiene los datos) SDL_DestroySurface(surface); return texture; }