| 84 | } |
| 85 | |
| 86 | static void setupImageConvert(CLI::App& image) |
| 87 | { |
| 88 | auto* cmd = image.add_subcommand("convert", "Convert image between formats"); |
| 89 | static std::string inputPath; |
| 90 | static std::string outputPath; |
| 91 | static std::string formatStr; |
| 92 | cmd->add_option("input", inputPath, "Input file (PAA/PAC/PNG/BMP/TGA/JPG)")->required()->check(CLI::ExistingFile); |
| 93 | cmd->add_option("output", outputPath, "Output file (PAA/PNG/BMP/TGA)")->required(); |
| 94 | cmd->add_option("-f,--format", formatStr, "Pixel format for PAA output (e.g., DXT1, DXT5, ARGB4444)"); |
| 95 | |
| 96 | cmd->callback( |
| 97 | []() |
| 98 | { |
| 99 | auto img = Poseidon::Image::FromFile(inputPath); |
| 100 | if (!img.valid()) |
| 101 | { |
| 102 | std::cerr << "Error: Failed to load: " << inputPath << std::endl; |
| 103 | throw CLI::RuntimeError(1); |
| 104 | } |
| 105 | |
| 106 | auto outExt = outputPath.substr(outputPath.find_last_of('.')); |
| 107 | std::string outExtLower = outExt; |
| 108 | std::transform(outExtLower.begin(), outExtLower.end(), outExtLower.begin(), ::tolower); |
| 109 | auto* ci = Poseidon::ImageContainerRegistry::FindByExtension(outExtLower.c_str()); |
| 110 | if (!ci) |
| 111 | { |
| 112 | std::cerr << "Error: Unsupported output format: " << outExt << std::endl; |
| 113 | throw CLI::RuntimeError(1); |
| 114 | } |
| 115 | |
| 116 | if (ci->container == Poseidon::ImageContainer::PAA) |
| 117 | { |
| 118 | Poseidon::PixelFormat fmt = Poseidon::PixelFormat::DXT5; |
| 119 | if (!formatStr.empty()) |
| 120 | { |
| 121 | auto* fi = Poseidon::PixelFormatRegistry::FindByName(formatStr.c_str()); |
| 122 | if (!fi) |
| 123 | { |
| 124 | std::cerr << "Error: Unknown pixel format: " << formatStr << std::endl; |
| 125 | std::cerr << "Use 'image formats' to list available formats." << std::endl; |
| 126 | throw CLI::RuntimeError(1); |
| 127 | } |
| 128 | if (fi->paaMagic == 0) |
| 129 | { |
| 130 | std::cerr << "Error: " << fi->name << " is not supported as PAA pixel format" << std::endl; |
| 131 | throw CLI::RuntimeError(1); |
| 132 | } |
| 133 | fmt = fi->format; |
| 134 | } |
| 135 | |
| 136 | if (!Poseidon::PAAEncoder::WritePAA(outputPath, img, fmt)) |
| 137 | { |
| 138 | std::cerr << "Error: Failed to write PAA: " << outputPath << std::endl; |
| 139 | throw CLI::RuntimeError(1); |
| 140 | } |
| 141 | const auto& fmtInfo = Poseidon::PixelFormatRegistry::Get(fmt); |
| 142 | std::cout << "Converted: " << inputPath << " -> " << outputPath << " (" << fmtInfo.name << ")" |
| 143 | << std::endl; |