10#include "imgui/imgui.h"
17 selected_format_(gfx::BppFormat::kBpp8),
18 preview_format_(gfx::BppFormat::kBpp8),
19 show_analysis_(false),
21 show_sheet_analysis_(false),
22 format_changed_(false),
23 last_analysis_sheet_(
"") {}
34 ImGui::Text(tr(
"BPP Format Selection"));
42 tr(
"Current Format: %s"),
46 ImGui::Text(tr(
"Target Format:"));
49 const char* format_names[] = {
"2BPP",
"3BPP",
"4BPP",
"8BPP"};
50 int current_selection =
53 if (ImGui::Combo(
"##BppFormat", ¤t_selection, format_names, 4)) {
59 const auto& format_info =
61 ImGui::Text(tr(
"Max Colors: %d"), format_info.max_colors);
62 ImGui::Text(tr(
"Bytes per Tile: %d"), format_info.bytes_per_tile);
63 ImGui::Text(tr(
"Description: %s"), format_info.description.c_str());
68 ImGui::Text(tr(
"Conversion Efficiency: %d%%"), efficiency);
70 ImVec4 efficiency_color;
71 if (efficiency >= 80) {
73 }
else if (efficiency >= 60) {
78 ImGui::TextColored(efficiency_color, tr(
"Quality: %s"),
79 efficiency >= 80 ?
"Excellent"
80 : efficiency >= 60 ?
"Good"
87 if (ImGui::Button(tr(
"Convert Format"))) {
88 if (on_format_changed) {
95 if (ImGui::Button(tr(
"Show Analysis"))) {
100 if (ImGui::Button(tr(
"Preview Conversion"))) {
129 tr(
"Detected Format: %s"),
133 std::vector<int> color_usage(256, 0);
134 for (uint8_t pixel : bitmap.
vector()) {
135 color_usage[pixel]++;
139 for (
int count : color_usage) {
144 ImGui::Text(tr(
"Colors Used: %d / %d"), used_colors,
145 static_cast<int>(palette.
size()));
146 ImGui::Text(tr(
"Color Efficiency: %.1f%%"),
147 (
static_cast<float>(used_colors) / palette.
size()) * 100.0f);
150 if (ImGui::CollapsingHeader(tr(
"Color Usage Chart"))) {
156 ImGui::Text(tr(
"Format Recommendations:"));
158 if (used_colors <= 4) {
159 ImGui::TextColored(
GetSuccessColor(), tr(
"✓ 2BPP format would be optimal"));
160 }
else if (used_colors <= 8) {
161 ImGui::TextColored(
GetSuccessColor(), tr(
"✓ 3BPP format would be optimal"));
162 }
else if (used_colors <= 16) {
163 ImGui::TextColored(
GetSuccessColor(), tr(
"✓ 4BPP format would be optimal"));
165 ImGui::TextColored(
GetWarningColor(), tr(
"⚠ 8BPP format is necessary"));
169 if (ImGui::CollapsingHeader(tr(
"Memory Usage Comparison"))) {
170 const auto& current_info =
173 (bitmap.
width() * bitmap.
height() * current_info.bits_per_pixel) / 8;
175 ImGui::Text(tr(
"Current Format (%s): %d bytes"), current_info.name.c_str(),
179 if (format == detected_format)
184 (bitmap.
width() * bitmap.
height() * info.bits_per_pixel) / 8;
185 float ratio =
static_cast<float>(format_bytes) / current_bytes;
187 ImGui::Text(tr(
"%s: %d bytes (%.1fx)"), info.name.c_str(), format_bytes,
203 if (current_format == target_format) {
204 ImGui::Text(tr(
"No conversion needed - formats are identical"));
211 bitmap.
vector(), current_format, target_format, bitmap.
width(),
216 converted_data, palette);
220 tr(
"Original (%s) vs Converted (%s)"),
224 ImGui::Columns(2,
"PreviewColumns");
227 ImGui::Text(tr(
"Original"));
229 ImGui::Image((ImTextureID)(intptr_t)bitmap.
texture(),
230 ImVec2(256, 256 * bitmap.
height() / bitmap.
width()));
236 ImGui::Text(tr(
"Converted"));
237 if (preview_bitmap.
texture()) {
239 (ImTextureID)(intptr_t)preview_bitmap.
texture(),
240 ImVec2(256, 256 * preview_bitmap.
height() / preview_bitmap.
width()));
247 ImGui::Text(tr(
"Conversion Statistics:"));
249 const auto& from_info =
251 const auto& to_info =
255 (bitmap.
width() * bitmap.
height() * from_info.bits_per_pixel) / 8;
257 (bitmap.
width() * bitmap.
height() * to_info.bits_per_pixel) / 8;
259 ImGui::Text(tr(
"Size: %d bytes -> %d bytes"), from_bytes, to_bytes);
260 ImGui::Text(tr(
"Compression Ratio: %.2fx"),
261 static_cast<float>(from_bytes) / to_bytes);
269 std::string analysis_key =
"sheet_" + std::to_string(sheet_id);
274 sheet_data, sheet_id, palette);
283 const auto& analysis = it->second;
287 ImGui::Text(tr(
"Sheet ID: %d"), analysis.sheet_id);
288 ImGui::Text(tr(
"Original Format: %s"),
290 .GetFormatInfo(analysis.original_format)
292 ImGui::Text(tr(
"Current Format: %s"),
294 .GetFormatInfo(analysis.current_format)
297 if (analysis.was_converted) {
298 ImGui::TextColored(
GetWarningColor(), tr(
"⚠ This sheet was converted"));
299 ImGui::Text(tr(
"Conversion History: %s"),
300 analysis.conversion_history.c_str());
302 ImGui::TextColored(
GetSuccessColor(), tr(
"✓ Original format preserved"));
306 ImGui::Text(tr(
"Color Usage: %d / %d colors used"),
307 analysis.palette_entries_used,
static_cast<int>(palette.
size()));
308 ImGui::Text(tr(
"Compression Ratio: %.2fx"), analysis.compression_ratio);
309 ImGui::Text(tr(
"Size: %zu -> %zu bytes"), analysis.original_size,
310 analysis.current_size);
313 if (ImGui::CollapsingHeader(tr(
"Tile Usage Pattern"))) {
314 int total_tiles = analysis.tile_usage_pattern.size();
318 for (
int usage : analysis.tile_usage_pattern) {
326 ImGui::Text(tr(
"Total Tiles: %d"), total_tiles);
327 ImGui::Text(tr(
"Used Tiles: %d (%.1f%%)"), used_tiles,
328 (
static_cast<float>(used_tiles) / total_tiles) * 100.0f);
329 ImGui::Text(tr(
"Empty Tiles: %d (%.1f%%)"), empty_tiles,
330 (
static_cast<float>(empty_tiles) / total_tiles) * 100.0f);
335 ImGui::Text(tr(
"Recommendations:"));
337 if (analysis.was_converted && analysis.palette_entries_used <= 16) {
340 tr(
"✓ Consider reverting to %s format for better compression"),
342 .GetFormatInfo(analysis.original_format)
346 if (analysis.palette_entries_used <
static_cast<int>(palette.
size()) / 2) {
349 tr(
"⚠ Palette is underutilized - consider optimization"));
358 return from_format != to_format;
364 if (from_format == to_format)
368 if (
static_cast<int>(from_format) >
static_cast<int>(to_format)) {
369 int bpp_diff =
static_cast<int>(from_format) -
static_cast<int>(to_format);
371 20, 100 - (bpp_diff * 20));
379 ImGui::Text(tr(
"Format: %s"), info.
name.c_str());
381 ImGui::Text(tr(
"Max Colors: %d"), info.
max_colors);
383 ImGui::Text(tr(
"Compressed: %s"), info.
is_compressed ?
"Yes" :
"No");
384 ImGui::Text(tr(
"Description: %s"), info.
description.c_str());
389 int max_usage = *std::max_element(color_usage.begin(), color_usage.end());
394 ImGui::Text(tr(
"Color Usage Distribution:"));
396 for (
size_t i = 0; i < std::min(color_usage.size(),
size_t(16)); ++i) {
397 if (color_usage[i] > 0) {
398 float usage_ratio =
static_cast<float>(color_usage[i]) / max_usage;
399 ImGui::Text(tr(
"Color %zu: %d pixels (%.1f%%)"), i, color_usage[i],
400 (
static_cast<float>(color_usage[i]) / (16 * 16)) * 100.0f);
402 ImGui::ProgressBar(usage_ratio, ImVec2(100, 0));
408 ImGui::Text(tr(
"Conversion History:"));
409 ImGui::TextWrapped(
"%s", history.c_str());
419 return ImVec4(1, 0, 0, 1);
421 return ImVec4(1, 1, 0, 1);
423 return ImVec4(0, 1, 0, 1);
425 return ImVec4(0, 0, 1, 1);
427 return ImVec4(1, 1, 1, 1);
441 target_format_(gfx::BppFormat::kBpp8),
442 preserve_palette_(true),
443 preview_valid_(false),
445 preview_scale_(1.0f) {}
461 ImGui::OpenPopup(
"BPP Format Conversion");
463 if (ImGui::BeginPopupModal(
"BPP Format Conversion", &
is_open_,
464 ImGuiWindowFlags_AlwaysAutoResize)) {
507 ImGui::Text(tr(
"Convert to BPP Format:"));
509 const char* format_names[] = {
"2BPP",
"3BPP",
"4BPP",
"8BPP"};
512 if (ImGui::Combo(
"##TargetFormat", ¤t_selection, format_names, 4)) {
517 const auto& format_info =
519 ImGui::Text(tr(
"Max Colors: %d"), format_info.max_colors);
520 ImGui::Text(tr(
"Description: %s"), format_info.description.c_str());
524 if (ImGui::Button(tr(
"Update Preview"))) {
531 ImGui::Text(tr(
"Preview:"));
546 if (ImGui::Button(tr(
"Convert"))) {
554 if (ImGui::Button(tr(
"Cancel"))) {
565 comparison_scale_(1.0f),
567 selected_comparison_(gfx::BppFormat::kBpp8) {}
581 ImGui::Begin(
"BPP Format Comparison", &
is_open_);
600 if (format == source_format) {
627 ImGui::Columns(2,
"ComparisonColumns");
634 const auto& bitmap = it->second;
635 const auto& format_info =
638 ImGui::Text(
"%s", format_info.name.c_str());
641 ImGui::Image((ImTextureID)(intptr_t)bitmap.
texture(),
652 ImGui::Text(tr(
"Format Metrics:"));
658 const auto& format_info =
662 ImGui::Text(
"%s: %s", format_info.name.c_str(), metrics.c_str());
667 ImGui::Text(tr(
"Selected for Analysis: "));
670 const char* format_names[] = {
"2BPP",
"3BPP",
"4BPP",
"8BPP"};
673 if (ImGui::Combo(
"##SelectedFormat", &selection, format_names, 4)) {
684 format_info.bits_per_pixel) /
687 std::ostringstream metrics;
688 metrics << bytes <<
" bytes, " << format_info.
max_colors <<
" colors";
690 return metrics.str();
Represents a bitmap image optimized for SNES ROM hacking.
TextureHandle texture() const
const std::vector< uint8_t > & vector() const
Represents a palette of colors for the Super Nintendo Entertainment System (SNES).
void RenderFormatSelector()
std::function< void(gfx::BppFormat, bool)> convert_callback_
BppConversionDialog(const std::string &id)
Constructor.
bool Render()
Render the dialog.
gfx::SnesPalette source_palette_
gfx::Bitmap source_bitmap_
void Show(const gfx::Bitmap &bitmap, const gfx::SnesPalette &palette, std::function< void(gfx::BppFormat, bool)> on_convert)
Show the conversion dialog.
gfx::Bitmap preview_bitmap_
gfx::BppFormat target_format_
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)
Graphics sheet analysis result.