9#include "imgui/imgui.h"
15 : id_(id), selected_format_(gfx::BppFormat::kBpp8), preview_format_(gfx::BppFormat::kBpp8),
16 show_analysis_(false), show_preview_(false), show_sheet_analysis_(false),
17 format_changed_(false), last_analysis_sheet_(
"") {
22 if (!bitmap)
return false;
27 ImGui::Text(
"BPP Format Selection");
34 ImGui::Text(
"Current Format: %s",
38 ImGui::Text(
"Target Format:");
41 const char* format_names[] = {
"2BPP",
"3BPP",
"4BPP",
"8BPP"};
44 if (ImGui::Combo(
"##BppFormat", ¤t_selection, format_names, 4)) {
51 ImGui::Text(
"Max Colors: %d", format_info.max_colors);
52 ImGui::Text(
"Bytes per Tile: %d", format_info.bytes_per_tile);
53 ImGui::Text(
"Description: %s", format_info.description.c_str());
58 ImGui::Text(
"Conversion Efficiency: %d%%", efficiency);
60 ImVec4 efficiency_color;
61 if (efficiency >= 80) {
63 }
else if (efficiency >= 60) {
68 ImGui::TextColored(efficiency_color,
"Quality: %s",
69 efficiency >= 80 ?
"Excellent" :
70 efficiency >= 60 ?
"Good" :
"Poor");
76 if (ImGui::Button(
"Convert Format")) {
77 if (on_format_changed) {
84 if (ImGui::Button(
"Show Analysis")) {
89 if (ImGui::Button(
"Preview Conversion")) {
116 ImGui::Text(
"Detected Format: %s",
120 std::vector<int> color_usage(256, 0);
121 for (uint8_t pixel : bitmap.
vector()) {
122 color_usage[pixel]++;
126 for (
int count : color_usage) {
127 if (count > 0) used_colors++;
130 ImGui::Text(
"Colors Used: %d / %d", used_colors,
static_cast<int>(palette.
size()));
131 ImGui::Text(
"Color Efficiency: %.1f%%",
132 (
static_cast<float>(used_colors) / palette.
size()) * 100.0f);
135 if (ImGui::CollapsingHeader(
"Color Usage Chart")) {
141 ImGui::Text(
"Format Recommendations:");
143 if (used_colors <= 4) {
144 ImGui::TextColored(
GetSuccessColor(),
"✓ 2BPP format would be optimal");
145 }
else if (used_colors <= 8) {
146 ImGui::TextColored(
GetSuccessColor(),
"✓ 3BPP format would be optimal");
147 }
else if (used_colors <= 16) {
148 ImGui::TextColored(
GetSuccessColor(),
"✓ 4BPP format would be optimal");
154 if (ImGui::CollapsingHeader(
"Memory Usage Comparison")) {
156 int current_bytes = (bitmap.
width() * bitmap.
height() * current_info.bits_per_pixel) / 8;
158 ImGui::Text(
"Current Format (%s): %d bytes", current_info.name.c_str(), current_bytes);
161 if (format == detected_format)
continue;
164 int format_bytes = (bitmap.
width() * bitmap.
height() * info.bits_per_pixel) / 8;
165 float ratio =
static_cast<float>(format_bytes) / current_bytes;
167 ImGui::Text(
"%s: %d bytes (%.1fx)", info.name.c_str(), format_bytes, ratio);
181 if (current_format == target_format) {
182 ImGui::Text(
"No conversion needed - formats are identical");
189 bitmap.
vector(), current_format, target_format, bitmap.
width(), bitmap.
height());
193 converted_data, palette);
196 ImGui::Text(
"Original (%s) vs Converted (%s)",
200 ImGui::Columns(2,
"PreviewColumns");
203 ImGui::Text(
"Original");
205 ImGui::Image((ImTextureID)(intptr_t)bitmap.
texture(),
206 ImVec2(256, 256 * bitmap.
height() / bitmap.
width()));
212 ImGui::Text(
"Converted");
213 if (preview_bitmap.
texture()) {
214 ImGui::Image((ImTextureID)(intptr_t)preview_bitmap.
texture(),
215 ImVec2(256, 256 * preview_bitmap.
height() / preview_bitmap.
width()));
222 ImGui::Text(
"Conversion Statistics:");
227 int from_bytes = (bitmap.
width() * bitmap.
height() * from_info.bits_per_pixel) / 8;
228 int to_bytes = (bitmap.
width() * bitmap.
height() * to_info.bits_per_pixel) / 8;
230 ImGui::Text(
"Size: %d bytes -> %d bytes", from_bytes, to_bytes);
231 ImGui::Text(
"Compression Ratio: %.2fx",
static_cast<float>(from_bytes) / to_bytes);
238 std::string analysis_key =
"sheet_" + std::to_string(sheet_id);
250 const auto& analysis = it->second;
254 ImGui::Text(
"Sheet ID: %d", analysis.sheet_id);
255 ImGui::Text(
"Original Format: %s",
257 ImGui::Text(
"Current Format: %s",
260 if (analysis.was_converted) {
262 ImGui::Text(
"Conversion History: %s", analysis.conversion_history.c_str());
268 ImGui::Text(
"Color Usage: %d / %d colors used",
269 analysis.palette_entries_used,
static_cast<int>(palette.
size()));
270 ImGui::Text(
"Compression Ratio: %.2fx", analysis.compression_ratio);
271 ImGui::Text(
"Size: %zu -> %zu bytes", analysis.original_size, analysis.current_size);
274 if (ImGui::CollapsingHeader(
"Tile Usage Pattern")) {
275 int total_tiles = analysis.tile_usage_pattern.size();
279 for (
int usage : analysis.tile_usage_pattern) {
287 ImGui::Text(
"Total Tiles: %d", total_tiles);
288 ImGui::Text(
"Used Tiles: %d (%.1f%%)", used_tiles,
289 (
static_cast<float>(used_tiles) / total_tiles) * 100.0f);
290 ImGui::Text(
"Empty Tiles: %d (%.1f%%)", empty_tiles,
291 (
static_cast<float>(empty_tiles) / total_tiles) * 100.0f);
296 ImGui::Text(
"Recommendations:");
298 if (analysis.was_converted && analysis.palette_entries_used <= 16) {
300 "✓ Consider reverting to %s format for better compression",
304 if (analysis.palette_entries_used <
static_cast<int>(palette.
size()) / 2) {
306 "⚠ Palette is underutilized - consider optimization");
314 return from_format != to_format;
319 if (from_format == to_format)
return 100;
322 if (
static_cast<int>(from_format) >
static_cast<int>(to_format)) {
323 int bpp_diff =
static_cast<int>(from_format) -
static_cast<int>(to_format);
324 return std::max(20, 100 - (bpp_diff * 20));
332 ImGui::Text(
"Format: %s", info.
name.c_str());
334 ImGui::Text(
"Max Colors: %d", info.
max_colors);
336 ImGui::Text(
"Compressed: %s", info.
is_compressed ?
"Yes" :
"No");
337 ImGui::Text(
"Description: %s", info.
description.c_str());
342 int max_usage = *std::max_element(color_usage.begin(), color_usage.end());
343 if (max_usage == 0)
return;
346 ImGui::Text(
"Color Usage Distribution:");
348 for (
size_t i = 0; i < std::min(color_usage.size(),
size_t(16)); ++i) {
349 if (color_usage[i] > 0) {
350 float usage_ratio =
static_cast<float>(color_usage[i]) / max_usage;
351 ImGui::Text(
"Color %zu: %d pixels (%.1f%%)", i, color_usage[i],
352 (
static_cast<float>(color_usage[i]) / (16 * 16)) * 100.0f);
354 ImGui::ProgressBar(usage_ratio, ImVec2(100, 0));
360 ImGui::Text(
"Conversion History:");
361 ImGui::TextWrapped(
"%s", history.c_str());
374 default:
return ImVec4(1, 1, 1, 1);
385 : id_(id), is_open_(false), target_format_(gfx::BppFormat::kBpp8),
386 preserve_palette_(true), preview_valid_(false), show_preview_(true), preview_scale_(1.0f) {
401 ImGui::OpenPopup(
"BPP Format Conversion");
403 if (ImGui::BeginPopupModal(
"BPP Format Conversion", &
is_open_,
404 ImGuiWindowFlags_AlwaysAutoResize)) {
446 ImGui::Text(
"Convert to BPP Format:");
448 const char* format_names[] = {
"2BPP",
"3BPP",
"4BPP",
"8BPP"};
451 if (ImGui::Combo(
"##TargetFormat", ¤t_selection, format_names, 4)) {
457 ImGui::Text(
"Max Colors: %d", format_info.max_colors);
458 ImGui::Text(
"Description: %s", format_info.description.c_str());
462 if (ImGui::Button(
"Update Preview")) {
469 ImGui::Text(
"Preview:");
484 if (ImGui::Button(
"Convert")) {
492 if (ImGui::Button(
"Cancel")) {
500 : id_(id), is_open_(false), has_source_(false), comparison_scale_(1.0f),
501 show_metrics_(true), selected_comparison_(gfx::BppFormat::kBpp8) {
514 ImGui::Begin(
"BPP Format Comparison", &
is_open_);
533 if (format == source_format) {
559 ImGui::Columns(2,
"ComparisonColumns");
565 const auto& bitmap = it->second;
568 ImGui::Text(
"%s", format_info.name.c_str());
571 ImGui::Image((ImTextureID)(intptr_t)bitmap.
texture(),
582 ImGui::Text(
"Format Metrics:");
590 ImGui::Text(
"%s: %s", format_info.name.c_str(), metrics.c_str());
595 ImGui::Text(
"Selected for Analysis: ");
598 const char* format_names[] = {
"2BPP",
"3BPP",
"4BPP",
"8BPP"};
601 if (ImGui::Combo(
"##SelectedFormat", &selection, format_names, 4)) {
613 std::ostringstream metrics;
614 metrics << bytes <<
" bytes, " << format_info.
max_colors <<
" colors";
616 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)
Main namespace for the application.
Graphics sheet analysis result.