28 const std::vector<uint8_t>& sheet_data,
int sheet_id,
40 result.
message =
"Sheet is not suitable for optimization";
47 result.
message =
"Optimization does not meet criteria";
63 result.
message =
"Optimization benefits do not justify quality loss";
68 result.
message =
"Optimization recommended";
78 }
catch (
const std::exception& e) {
80 result.
message =
"Optimization failed: " + std::string(e.what());
81 SDL_Log(
"GraphicsOptimizer::OptimizeSheet failed: %s", e.what());
88 const std::unordered_map<
int, std::vector<uint8_t>>& sheets,
89 const std::unordered_map<int, SnesPalette>& palettes,
96 size_t total_memory_saved = 0;
97 float total_performance_gain = 0.0f;
98 float total_quality_loss = 0.0f;
99 int optimized_sheets = 0;
101 for (
const auto& [sheet_id, sheet_data] : sheets) {
102 auto palette_it = palettes.find(sheet_id);
103 if (palette_it == palettes.end()) {
108 OptimizeSheet(sheet_data, sheet_id, palette_it->second, strategy);
110 if (sheet_result.success) {
111 total_memory_saved += sheet_result.memory_saved;
112 total_performance_gain += sheet_result.performance_gain;
113 total_quality_loss += sheet_result.quality_loss;
119 sheet_result.recommended_formats.begin(),
120 sheet_result.recommended_formats.end());
122 sheet_result.sheet_recommendations.begin(),
123 sheet_result.sheet_recommendations.end());
129 optimized_sheets > 0 ? total_performance_gain / optimized_sheets : 0.0f;
131 optimized_sheets > 0 ? total_quality_loss / optimized_sheets : 0.0f;
133 if (optimized_sheets > 0) {
135 "Optimized " + std::to_string(optimized_sheets) +
" sheets";
138 result.
message =
"No sheets could be optimized";
143 static_cast<double>(sheets.size()));
149 const std::vector<uint8_t>& sheet_data,
int sheet_id,
155 return cache_it->second;
166 sheet_data, 128, 32);
176 const auto& current_info =
178 const auto& recommended_info =
181 data.
optimized_size = (sheet_data.size() * recommended_info.bits_per_pixel) /
182 current_info.bits_per_pixel;
189 (data.
colors_used <= recommended_info.max_colors) &&
200std::unordered_map<int, SheetOptimizationData>
202 const std::unordered_map<
int, std::vector<uint8_t>>& sheets,
203 const std::unordered_map<int, SnesPalette>& palettes) {
205 std::unordered_map<int, SheetOptimizationData> recommendations;
207 for (
const auto& [sheet_id, sheet_data] : sheets) {
208 auto palette_it = palettes.find(sheet_id);
209 if (palette_it == palettes.end()) {
213 recommendations[sheet_id] =
217 return recommendations;
221 const std::unordered_map<int, SheetOptimizationData>& recommendations,
222 std::unordered_map<
int, std::vector<uint8_t>>& sheets,
223 std::unordered_map<int, SnesPalette>& palettes) {
230 size_t total_memory_saved = 0;
231 int optimized_sheets = 0;
233 for (
const auto& [sheet_id, data] : recommendations) {
234 if (!data.is_convertible) {
238 auto sheet_it = sheets.find(sheet_id);
239 if (sheet_it == sheets.end()) {
246 sheet_it->second, data.current_format, data.recommended_format, 128,
250 sheet_it->second = converted_data;
253 auto palette_it = palettes.find(sheet_id);
254 if (palette_it != palettes.end()) {
255 std::vector<int> used_colors;
256 for (
int i = 0; i < data.colors_used; ++i) {
257 used_colors.push_back(i);
261 palette_it->second, data.recommended_format, used_colors);
264 total_memory_saved += data.current_size - data.optimized_size;
269 }
catch (
const std::exception& e) {
270 SDL_Log(
"Failed to optimize sheet %d: %s", sheet_id, e.what());
275 result.
message =
"Optimized " + std::to_string(optimized_sheets) +
" sheets";
278 static_cast<double>(optimized_sheets));
280 static_cast<double>(total_memory_saved));
285std::unordered_map<std::string, double>
296 size_t min_memory_savings,
297 float performance_threshold) {
306 const std::vector<uint8_t>& data,
const SnesPalette& palette,
313 if (colors_used <= 4)
315 if (colors_used <= 8)
317 if (colors_used <= 16)
323 if (colors_used <= 16)
329 if (colors_used <= 4)
334 if (colors_used <= 4)
336 if (colors_used <= 8)
338 if (colors_used <= 16)
348 const std::vector<uint8_t>& data) {
349 if (from_format == to_format)
353 if (
static_cast<int>(from_format) >
static_cast<int>(to_format)) {
354 int bpp_diff =
static_cast<int>(from_format) -
static_cast<int>(to_format);
356 1.0f,
static_cast<float>(bpp_diff) * 0.1f);
364 const std::vector<uint8_t>& data) {
365 if (from_format == to_format)
371 size_t from_size = data.size();
375 return from_size - to_size;
380 if (from_format == to_format)
384 if (
static_cast<int>(from_format) >
static_cast<int>(to_format)) {
385 int bpp_diff =
static_cast<int>(from_format) -
static_cast<int>(to_format);
387 0.5f,
static_cast<float>(bpp_diff) * 0.1f);
417 std::ostringstream reason;
419 reason <<
"Convert from "
423 <<
" (uses " << data.
colors_used <<
" colors, " << std::fixed
425 <<
"% memory savings)";
432 std::vector<bool> used_colors(palette.
size(),
false);
434 for (uint8_t pixel : data) {
435 if (pixel < palette.
size()) {
436 used_colors[pixel] =
true;
441 for (
bool used : used_colors) {
450 const std::vector<uint8_t>& data,
const SnesPalette& palette) {
452 return static_cast<float>(used_colors) / palette.
size();
456 const std::vector<uint8_t>& data) {
457 std::vector<int> distribution(256, 0);
459 for (uint8_t pixel : data) {
460 distribution[pixel]++;
467 const std::vector<uint8_t>& data,
int sheet_id) {
468 std::ostringstream key;
469 key <<
"sheet_" << sheet_id <<
"_" << data.size();
473 for (
size_t i = 0; i < std::min(data.size(),
size_t(1024)); ++i) {
474 hash = hash * 31 + data[i];
490 : strategy_(strategy),
491 sheet_count_(sheet_count),
492 timer_(
"graphics_optimize_scope") {
493 std::ostringstream op_name;
494 op_name <<
"graphics_optimize_" <<
static_cast<int>(strategy) <<
"_"
504 size_t optimized_size) {
OptimizationResult result_
void SetResult(const OptimizationResult &result)
std::string operation_name_
~GraphicsOptimizationScope()
GraphicsOptimizationScope(OptimizationStrategy strategy, int sheet_count)
void AddSheet(int sheet_id, size_t original_size, size_t optimized_size)
Comprehensive graphics optimization system for YAZE ROM hacking.
std::unordered_map< std::string, SheetOptimizationData > optimization_cache_
void UpdateOptimizationStats(const std::string &operation, double value)
float CalculateColorEfficiency(const std::vector< uint8_t > &data, const SnesPalette &palette)
void Initialize()
Initialize the graphics optimizer.
BppFormat DetermineOptimalFormat(const std::vector< uint8_t > &data, const SnesPalette &palette, OptimizationStrategy strategy)
float CalculatePerformanceGain(BppFormat from_format, BppFormat to_format)
std::unordered_map< int, SheetOptimizationData > GetOptimizationRecommendations(const std::unordered_map< int, std::vector< uint8_t > > &sheets, const std::unordered_map< int, SnesPalette > &palettes)
Get optimization recommendations for all sheets.
float performance_threshold_
std::string GenerateOptimizationReason(const SheetOptimizationData &data)
int CountUsedColors(const std::vector< uint8_t > &data, const SnesPalette &palette)
static GraphicsOptimizer & Get()
std::unordered_map< std::string, double > optimization_stats_
OptimizationResult ApplyOptimizations(const std::unordered_map< int, SheetOptimizationData > &recommendations, std::unordered_map< int, std::vector< uint8_t > > &sheets, std::unordered_map< int, SnesPalette > &palettes)
Apply optimization recommendations.
SheetOptimizationData AnalyzeSheet(const std::vector< uint8_t > &sheet_data, int sheet_id, const SnesPalette &palette)
Analyze graphics sheet for optimization opportunities.
OptimizationResult OptimizeSheets(const std::unordered_map< int, std::vector< uint8_t > > &sheets, const std::unordered_map< int, SnesPalette > &palettes, OptimizationStrategy strategy=OptimizationStrategy::kBalanced)
Optimize multiple graphics sheets.
std::unordered_map< std::string, double > GetOptimizationStats() const
Get optimization statistics.
size_t CalculateMemorySavings(BppFormat from_format, BppFormat to_format, const std::vector< uint8_t > &data)
void SetOptimizationParameters(float max_quality_loss=0.1f, size_t min_memory_savings=1024, float performance_threshold=0.05f)
Set optimization parameters.
size_t min_memory_savings_
bool ShouldOptimize(const SheetOptimizationData &data, OptimizationStrategy strategy)
OptimizationResult OptimizeSheet(const std::vector< uint8_t > &sheet_data, int sheet_id, const SnesPalette &palette, OptimizationStrategy strategy=OptimizationStrategy::kBalanced)
Optimize a single graphics sheet.
float CalculateQualityLoss(BppFormat from_format, BppFormat to_format, const std::vector< uint8_t > &data)
void ClearCache()
Clear optimization cache.
std::vector< int > AnalyzeColorDistribution(const std::vector< uint8_t > &data)
std::string GenerateCacheKey(const std::vector< uint8_t > &data, int sheet_id)
RAII timer for automatic timing management.
Represents a palette of colors for the Super Nintendo Entertainment System (SNES).
OptimizationStrategy
Graphics optimization strategy.
@ kBalanced
Balance memory, performance, and quality.
@ kPerformanceOptimized
Maximize rendering performance.
@ kMemoryOptimized
Minimize memory usage.
@ kQualityOptimized
Maintain highest quality.
BppFormat
BPP format enumeration for SNES graphics.
@ kBpp4
4 bits per pixel (16 colors)
@ kBpp3
3 bits per pixel (8 colors)
@ kBpp2
2 bits per pixel (4 colors)
@ kBpp8
8 bits per pixel (256 colors)
Main namespace for the application.
Graphics optimization result.
std::vector< BppFormat > recommended_formats
std::unordered_map< int, BppFormat > sheet_recommendations
Graphics sheet optimization data.
std::string optimization_reason
BppFormat recommended_format