diff --git a/src/openrct2/CmdlineSprite.cpp b/src/openrct2/CmdlineSprite.cpp index b7a50b1410..e24d9fd49b 100644 --- a/src/openrct2/CmdlineSprite.cpp +++ b/src/openrct2/CmdlineSprite.cpp @@ -225,7 +225,8 @@ static bool SpriteImageExport(const rct_g1_element& spriteElement, const char* o } static std::optional SpriteImageImport( - const char* path, int16_t x_offset, int16_t y_offset, bool keep_palette, bool forceBmp, int32_t mode) + const char* path, int16_t x_offset, int16_t y_offset, ImageImporter::PALETTE palette, bool forceBmp, + ImageImporter::IMPORT_MODE mode) { try { @@ -237,16 +238,15 @@ static std::optional SpriteImageImport( flags = ImageImporter::IMPORT_FLAGS::RLE; } - if (keep_palette) + if (palette == ImageImporter::PALETTE::KEEP_INDICES) { format = IMAGE_FORMAT::PNG; - flags = static_cast(flags | ImageImporter::IMPORT_FLAGS::KEEP_PALETTE); } ImageImporter importer; auto image = Imaging::ReadFromFile(path, format); - return importer.Import(image, x_offset, y_offset, flags, static_cast(mode)); + return importer.Import(image, x_offset, y_offset, palette, flags, mode); } catch (const std::exception& e) { @@ -549,7 +549,8 @@ int32_t cmdline_for_sprite(const char** argv, int32_t argc) } } - auto importResult = SpriteImageImport(imagePath, x_offset, y_offset, false, false, gSpriteMode); + auto importResult = SpriteImageImport( + imagePath, x_offset, y_offset, ImageImporter::PALETTE::OPENRCT2, false, gSpriteMode); if (!importResult.has_value()) return -1; @@ -625,14 +626,15 @@ int32_t cmdline_for_sprite(const char** argv, int32_t argc) json_t x_offset = jsonSprite["x_offset"]; json_t y_offset = jsonSprite["y_offset"]; - bool keep_palette = Json::GetString(jsonSprite["palette"]) == "keep"; + auto palette = (Json::GetString(jsonSprite["palette"]) == "keep") ? ImageImporter::PALETTE::KEEP_INDICES + : ImageImporter::PALETTE::OPENRCT2; bool forceBmp = !jsonSprite["palette"].is_null() && Json::GetBoolean(jsonSprite["forceBmp"]); auto imagePath = Path::GetAbsolute(std::string(directoryPath) + "/" + strPath); auto importResult = SpriteImageImport( - imagePath.c_str(), Json::GetNumber(x_offset), Json::GetNumber(y_offset), keep_palette, - forceBmp, gSpriteMode); + imagePath.c_str(), Json::GetNumber(x_offset), Json::GetNumber(y_offset), palette, forceBmp, + gSpriteMode); if (importResult == std::nullopt) { fprintf(stderr, "Could not import image file: %s\nCanceling\n", imagePath.c_str()); diff --git a/src/openrct2/CmdlineSprite.h b/src/openrct2/CmdlineSprite.h index e9f4e65686..093772a31b 100644 --- a/src/openrct2/CmdlineSprite.h +++ b/src/openrct2/CmdlineSprite.h @@ -10,6 +10,7 @@ #pragma once #include "common.h" +#include "drawing/ImageImporter.h" int32_t cmdline_for_sprite(const char** argv, int32_t argc); -extern int32_t gSpriteMode; +extern OpenRCT2::Drawing::ImageImporter::IMPORT_MODE gSpriteMode; diff --git a/src/openrct2/cmdline/SpriteCommands.cpp b/src/openrct2/cmdline/SpriteCommands.cpp index d2e347a44f..e56707448d 100644 --- a/src/openrct2/cmdline/SpriteCommands.cpp +++ b/src/openrct2/cmdline/SpriteCommands.cpp @@ -16,7 +16,9 @@ #define SZ_CLOSEST "closest" #define SZ_DITHERING "dithering" -int32_t gSpriteMode = 0; +using IMPORT_MODE = OpenRCT2::Drawing::ImageImporter::IMPORT_MODE; + +IMPORT_MODE gSpriteMode = IMPORT_MODE::DEFAULT; static const char* _mode; @@ -47,9 +49,9 @@ const CommandLineCommand CommandLine::SpriteCommands[] static exitcode_t HandleSprite(CommandLineArgEnumerator* argEnumerator) { if (String::Equals(_mode, SZ_CLOSEST, true)) - gSpriteMode = 1; + gSpriteMode = IMPORT_MODE::CLOSEST; else if (String::Equals(_mode, SZ_DITHERING, true)) - gSpriteMode = 2; + gSpriteMode = IMPORT_MODE::DITHERING; Memory::Free(_mode); const char** argv = const_cast(argEnumerator->GetArguments()) + argEnumerator->GetIndex() - 1; diff --git a/src/openrct2/drawing/ImageImporter.cpp b/src/openrct2/drawing/ImageImporter.cpp index e03300bd58..e5311bc79d 100644 --- a/src/openrct2/drawing/ImageImporter.cpp +++ b/src/openrct2/drawing/ImageImporter.cpp @@ -21,26 +21,26 @@ using ImportResult = ImageImporter::ImportResult; constexpr int32_t PALETTE_TRANSPARENT = -1; ImportResult ImageImporter::Import( - const Image& image, int32_t offsetX, int32_t offsetY, IMPORT_FLAGS flags, IMPORT_MODE mode) const + const Image& image, int32_t offsetX, int32_t offsetY, PALETTE palette, IMPORT_FLAGS flags, IMPORT_MODE mode) const { - return Import(image, 0, 0, image.Width, image.Height, offsetX, offsetY, flags, mode); + return Import(image, 0, 0, image.Width, image.Height, offsetX, offsetY, palette, flags, mode); } ImportResult ImageImporter::Import( const Image& image, int32_t srcX, int32_t srcY, int32_t width, int32_t height, int32_t offsetX, int32_t offsetY, - IMPORT_FLAGS flags, IMPORT_MODE mode) const + PALETTE palette, IMPORT_FLAGS flags, IMPORT_MODE mode) const { if (width > 256 || height > 256) { throw std::invalid_argument("Only images 256x256 or less are supported."); } - if ((flags & IMPORT_FLAGS::KEEP_PALETTE) && image.Depth != 8) + if (palette == PALETTE::KEEP_INDICES && image.Depth != 8) { throw std::invalid_argument("Image is not paletted, it has bit depth of " + std::to_string(image.Depth)); } - auto pixels = GetPixels(image.Pixels.data(), image.Stride, srcX, srcY, width, height, flags, mode); + auto pixels = GetPixels(image.Pixels.data(), image.Stride, srcX, srcY, width, height, palette, flags, mode); auto buffer = flags & IMPORT_FLAGS::RLE ? EncodeRLE(pixels.data(), width, height) : EncodeRaw(pixels.data(), width, height); rct_g1_element outElement; @@ -59,8 +59,8 @@ ImportResult ImageImporter::Import( } std::vector ImageImporter::GetPixels( - const uint8_t* pixels, uint32_t pitch, uint32_t srcX, uint32_t srcY, uint32_t width, uint32_t height, IMPORT_FLAGS flags, - IMPORT_MODE mode) + const uint8_t* pixels, uint32_t pitch, uint32_t srcX, uint32_t srcY, uint32_t width, uint32_t height, PALETTE palette, + IMPORT_FLAGS flags, IMPORT_MODE mode) { std::vector buffer; buffer.reserve(width * height); @@ -68,13 +68,13 @@ std::vector ImageImporter::GetPixels( // A larger range is needed for proper dithering auto palettedSrc = pixels; std::unique_ptr rgbaSrcBuffer; - if (!(flags & IMPORT_FLAGS::KEEP_PALETTE)) + if (palette != PALETTE::KEEP_INDICES) { rgbaSrcBuffer = std::make_unique(height * width * 4); } auto rgbaSrc = rgbaSrcBuffer.get(); - if (!(flags & IMPORT_FLAGS::KEEP_PALETTE)) + if (palette != PALETTE::KEEP_INDICES) { auto src = pixels + (srcY * pitch) + (srcX * 4); auto dst = rgbaSrc; @@ -90,7 +90,7 @@ std::vector ImageImporter::GetPixels( } } - if (flags & IMPORT_FLAGS::KEEP_PALETTE) + if (palette == PALETTE::KEEP_INDICES) { palettedSrc += srcX + srcY * pitch; for (uint32_t y = 0; y < height; y++) diff --git a/src/openrct2/drawing/ImageImporter.h b/src/openrct2/drawing/ImageImporter.h index 1ff1bc37d8..e01879e220 100644 --- a/src/openrct2/drawing/ImageImporter.h +++ b/src/openrct2/drawing/ImageImporter.h @@ -41,16 +41,22 @@ namespace OpenRCT2::Drawing enum IMPORT_FLAGS { NONE = 0, - KEEP_PALETTE = 1 << 0, RLE = 1 << 1, }; + enum class PALETTE : uint8_t + { + OPENRCT2, + KEEP_INDICES, + }; + ImportResult Import( const Image& image, int32_t srcX, int32_t srcY, int32_t width, int32_t height, int32_t offsetX, int32_t offsetY, - IMPORT_FLAGS flags = IMPORT_FLAGS::NONE, IMPORT_MODE mode = IMPORT_MODE::DEFAULT) const; - ImportResult Import( - const Image& image, int32_t offsetX = 0, int32_t offsetY = 0, IMPORT_FLAGS flags = IMPORT_FLAGS::NONE, + PALETTE palette = PALETTE::OPENRCT2, IMPORT_FLAGS flags = IMPORT_FLAGS::NONE, IMPORT_MODE mode = IMPORT_MODE::DEFAULT) const; + ImportResult Import( + const Image& image, int32_t offsetX = 0, int32_t offsetY = 0, PALETTE palette = PALETTE::OPENRCT2, + IMPORT_FLAGS flags = IMPORT_FLAGS::NONE, IMPORT_MODE mode = IMPORT_MODE::DEFAULT) const; private: enum class PaletteIndexType : uint8_t @@ -64,7 +70,7 @@ namespace OpenRCT2::Drawing static std::vector GetPixels( const uint8_t* pixels, uint32_t pitch, uint32_t srcX, uint32_t srcY, uint32_t width, uint32_t height, - IMPORT_FLAGS flags, IMPORT_MODE mode); + PALETTE palette, IMPORT_FLAGS flags, IMPORT_MODE mode); static std::vector EncodeRaw(const int32_t* pixels, uint32_t width, uint32_t height); static std::vector EncodeRLE(const int32_t* pixels, uint32_t width, uint32_t height); diff --git a/src/openrct2/object/ImageTable.cpp b/src/openrct2/object/ImageTable.cpp index 209d0de855..a9f8ae2072 100644 --- a/src/openrct2/object/ImageTable.cpp +++ b/src/openrct2/object/ImageTable.cpp @@ -145,7 +145,8 @@ std::vector> ImageTable::ParseImages( auto image = Imaging::ReadFromBuffer(imageData); ImageImporter importer; - auto importResult = importer.Import(image, 0, 0, ImageImporter::IMPORT_FLAGS::RLE); + auto importResult = importer.Import( + image, 0, 0, ImageImporter::PALETTE::OPENRCT2, ImageImporter::IMPORT_FLAGS::RLE); result.push_back(std::make_unique(importResult.Element)); } @@ -179,13 +180,14 @@ std::vector> ImageTable::ParseImages( try { auto flags = ImageImporter::IMPORT_FLAGS::NONE; + auto palette = ImageImporter::PALETTE::OPENRCT2; if (!raw) { flags = static_cast(flags | ImageImporter::IMPORT_FLAGS::RLE); } if (keepPalette) { - flags = static_cast(flags | ImageImporter::IMPORT_FLAGS::KEEP_PALETTE); + palette = ImageImporter::PALETTE::KEEP_INDICES; } auto itSource = std::find_if( @@ -204,7 +206,7 @@ std::vector> ImageTable::ParseImages( srcHeight = image.Height; ImageImporter importer; - auto importResult = importer.Import(image, srcX, srcY, srcWidth, srcHeight, x, y, flags); + auto importResult = importer.Import(image, srcX, srcY, srcWidth, srcHeight, x, y, palette, flags); auto g1element = importResult.Element; g1element.zoomed_offset = zoomOffset; result.push_back(std::make_unique(g1element)); diff --git a/test/tests/ImageImporterTests.cpp b/test/tests/ImageImporterTests.cpp index 04f04d75d7..19e03c7114 100644 --- a/test/tests/ImageImporterTests.cpp +++ b/test/tests/ImageImporterTests.cpp @@ -41,7 +41,7 @@ TEST_F(ImageImporterTests, Import_Logo) ImageImporter importer; auto image = Imaging::ReadFromFile(logoPath, IMAGE_FORMAT::PNG_32); - auto result = importer.Import(image, 3, 5, ImageImporter::IMPORT_FLAGS::RLE); + auto result = importer.Import(image, 3, 5, ImageImporter::PALETTE::OPENRCT2, ImageImporter::IMPORT_FLAGS::RLE); ASSERT_EQ(result.Buffer.data(), result.Element.offset); ASSERT_EQ(128, result.Element.width);