9#include "imgui/imgui.h"
16 selected_format_(gfx::BppFormat::kBpp8),
17 preview_format_(gfx::BppFormat::kBpp8),
18 show_analysis_(false),
20 show_sheet_analysis_(false),
21 format_changed_(false),
22 last_analysis_sheet_(
"") {}
33 ImGui::Text(
"BPP Format Selection");
45 ImGui::Text(
"Target Format:");
48 const char* format_names[] = {
"2BPP",
"3BPP",
"4BPP",
"8BPP"};
49 int current_selection =
52 if (ImGui::Combo(
"##BppFormat", ¤t_selection, format_names, 4)) {
58 const auto& format_info =
60 ImGui::Text(
"Max Colors: %d", format_info.max_colors);
61 ImGui::Text(
"Bytes per Tile: %d", format_info.bytes_per_tile);
62 ImGui::Text(
"Description: %s", format_info.description.c_str());
67 ImGui::Text(
"Conversion Efficiency: %d%%", efficiency);
69 ImVec4 efficiency_color;
70 if (efficiency >= 80) {
72 }
else if (efficiency >= 60) {
77 ImGui::TextColored(efficiency_color,
"Quality: %s",
78 efficiency >= 80 ?
"Excellent"
79 : efficiency >= 60 ?
"Good"
86 if (ImGui::Button(
"Convert Format")) {
87 if (on_format_changed) {
94 if (ImGui::Button(
"Show Analysis")) {
99 if (ImGui::Button(
"Preview Conversion")) {
128 "Detected Format: %s",
132 std::vector<int> color_usage(256, 0);
133 for (uint8_t pixel : bitmap.
vector()) {
134 color_usage[pixel]++;
138 for (
int count : color_usage) {
143 ImGui::Text(
"Colors Used: %d / %d", used_colors,
144 static_cast<int>(palette.
size()));
145 ImGui::Text(
"Color Efficiency: %.1f%%",
146 (
static_cast<float>(used_colors) / palette.
size()) * 100.0f);
149 if (ImGui::CollapsingHeader(
"Color Usage Chart")) {
155 ImGui::Text(
"Format Recommendations:");
157 if (used_colors <= 4) {
158 ImGui::TextColored(
GetSuccessColor(),
"✓ 2BPP format would be optimal");
159 }
else if (used_colors <= 8) {
160 ImGui::TextColored(
GetSuccessColor(),
"✓ 3BPP format would be optimal");
161 }
else if (used_colors <= 16) {
162 ImGui::TextColored(
GetSuccessColor(),
"✓ 4BPP format would be optimal");
168 if (ImGui::CollapsingHeader(
"Memory Usage Comparison")) {
169 const auto& current_info =
172 (bitmap.
width() * bitmap.
height() * current_info.bits_per_pixel) / 8;
174 ImGui::Text(
"Current Format (%s): %d bytes", current_info.name.c_str(),
178 if (format == detected_format)
183 (bitmap.
width() * bitmap.
height() * info.bits_per_pixel) / 8;
184 float ratio =
static_cast<float>(format_bytes) / current_bytes;
186 ImGui::Text(
"%s: %d bytes (%.1fx)", info.name.c_str(), format_bytes,
202 if (current_format == target_format) {
203 ImGui::Text(
"No conversion needed - formats are identical");
210 bitmap.
vector(), current_format, target_format, bitmap.
width(),
215 converted_data, palette);
219 "Original (%s) vs Converted (%s)",
223 ImGui::Columns(2,
"PreviewColumns");
226 ImGui::Text(
"Original");
228 ImGui::Image((ImTextureID)(intptr_t)bitmap.
texture(),
229 ImVec2(256, 256 * bitmap.
height() / bitmap.
width()));
235 ImGui::Text(
"Converted");
236 if (preview_bitmap.
texture()) {
238 (ImTextureID)(intptr_t)preview_bitmap.
texture(),
239 ImVec2(256, 256 * preview_bitmap.
height() / preview_bitmap.
width()));
246 ImGui::Text(
"Conversion Statistics:");
248 const auto& from_info =
250 const auto& to_info =
254 (bitmap.
width() * bitmap.
height() * from_info.bits_per_pixel) / 8;
256 (bitmap.
width() * bitmap.
height() * to_info.bits_per_pixel) / 8;
258 ImGui::Text(
"Size: %d bytes -> %d bytes", from_bytes, to_bytes);
259 ImGui::Text(
"Compression Ratio: %.2fx",
260 static_cast<float>(from_bytes) / to_bytes);
268 std::string analysis_key =
"sheet_" + std::to_string(sheet_id);
273 sheet_data, sheet_id, palette);
282 const auto& analysis = it->second;
286 ImGui::Text(
"Sheet ID: %d", analysis.sheet_id);
287 ImGui::Text(
"Original Format: %s",
289 .GetFormatInfo(analysis.original_format)
292 .GetFormatInfo(analysis.current_format)
295 if (analysis.was_converted) {
297 ImGui::Text(
"Conversion History: %s", analysis.conversion_history.c_str());
303 ImGui::Text(
"Color Usage: %d / %d colors used", analysis.palette_entries_used,
304 static_cast<int>(palette.
size()));
305 ImGui::Text(
"Compression Ratio: %.2fx", analysis.compression_ratio);
306 ImGui::Text(
"Size: %zu -> %zu bytes", analysis.original_size,
307 analysis.current_size);
310 if (ImGui::CollapsingHeader(
"Tile Usage Pattern")) {
311 int total_tiles = analysis.tile_usage_pattern.size();
315 for (
int usage : analysis.tile_usage_pattern) {
323 ImGui::Text(
"Total Tiles: %d", total_tiles);
324 ImGui::Text(
"Used Tiles: %d (%.1f%%)", used_tiles,
325 (
static_cast<float>(used_tiles) / total_tiles) * 100.0f);
326 ImGui::Text(
"Empty Tiles: %d (%.1f%%)", empty_tiles,
327 (
static_cast<float>(empty_tiles) / total_tiles) * 100.0f);
332 ImGui::Text(
"Recommendations:");
334 if (analysis.was_converted && analysis.palette_entries_used <= 16) {
337 "✓ Consider reverting to %s format for better compression",
339 .GetFormatInfo(analysis.original_format)
343 if (analysis.palette_entries_used <
static_cast<int>(palette.
size()) / 2) {
345 "⚠ Palette is underutilized - consider optimization");
354 return from_format != to_format;
360 if (from_format == to_format)
364 if (
static_cast<int>(from_format) >
static_cast<int>(to_format)) {
365 int bpp_diff =
static_cast<int>(from_format) -
static_cast<int>(to_format);
367 20, 100 - (bpp_diff * 20));
375 ImGui::Text(
"Format: %s", info.
name.c_str());
377 ImGui::Text(
"Max Colors: %d", info.
max_colors);
379 ImGui::Text(
"Compressed: %s", info.
is_compressed ?
"Yes" :
"No");
380 ImGui::Text(
"Description: %s", info.
description.c_str());
385 int max_usage = *std::max_element(color_usage.begin(), color_usage.end());
390 ImGui::Text(
"Color Usage Distribution:");
392 for (
size_t i = 0; i < std::min(color_usage.size(),
size_t(16)); ++i) {
393 if (color_usage[i] > 0) {
394 float usage_ratio =
static_cast<float>(color_usage[i]) / max_usage;
395 ImGui::Text(
"Color %zu: %d pixels (%.1f%%)", i, color_usage[i],
396 (
static_cast<float>(color_usage[i]) / (16 * 16)) * 100.0f);
398 ImGui::ProgressBar(usage_ratio, ImVec2(100, 0));
404 ImGui::Text(
"Conversion History:");
405 ImGui::TextWrapped(
"%s", history.c_str());
415 return ImVec4(1, 0, 0, 1);
417 return ImVec4(1, 1, 0, 1);
419 return ImVec4(0, 1, 0, 1);
421 return ImVec4(0, 0, 1, 1);
423 return ImVec4(1, 1, 1, 1);
437 target_format_(gfx::BppFormat::kBpp8),
438 preserve_palette_(true),
439 preview_valid_(false),
441 preview_scale_(1.0f) {}
457 ImGui::OpenPopup(
"BPP Format Conversion");
459 if (ImGui::BeginPopupModal(
"BPP Format Conversion", &
is_open_,
460 ImGuiWindowFlags_AlwaysAutoResize)) {
503 ImGui::Text(
"Convert to BPP Format:");
505 const char* format_names[] = {
"2BPP",
"3BPP",
"4BPP",
"8BPP"};
508 if (ImGui::Combo(
"##TargetFormat", ¤t_selection, format_names, 4)) {
513 const auto& format_info =
515 ImGui::Text(
"Max Colors: %d", format_info.max_colors);
516 ImGui::Text(
"Description: %s", format_info.description.c_str());
520 if (ImGui::Button(
"Update Preview")) {
527 ImGui::Text(
"Preview:");
542 if (ImGui::Button(
"Convert")) {
550 if (ImGui::Button(
"Cancel")) {
561 comparison_scale_(1.0f),
563 selected_comparison_(gfx::BppFormat::kBpp8) {}
577 ImGui::Begin(
"BPP Format Comparison", &
is_open_);
596 if (format == source_format) {
623 ImGui::Columns(2,
"ComparisonColumns");
630 const auto& bitmap = it->second;
631 const auto& format_info =
634 ImGui::Text(
"%s", format_info.name.c_str());
637 ImGui::Image((ImTextureID)(intptr_t)bitmap.
texture(),
648 ImGui::Text(
"Format Metrics:");
654 const auto& format_info =
658 ImGui::Text(
"%s: %s", format_info.name.c_str(), metrics.c_str());
663 ImGui::Text(
"Selected for Analysis: ");
666 const char* format_names[] = {
"2BPP",
"3BPP",
"4BPP",
"8BPP"};
669 if (ImGui::Combo(
"##SelectedFormat", &selection, format_names, 4)) {
680 format_info.bits_per_pixel) /
683 std::ostringstream metrics;
684 metrics << bytes <<
" bytes, " << format_info.
max_colors <<
" colors";
686 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.