Clean up palette import

This commit is contained in:
Michael Steenbeek 2022-02-07 19:34:22 +01:00 committed by GitHub
parent 63ed6c99a5
commit 1062c3d08d
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
7 changed files with 44 additions and 31 deletions

View file

@ -225,7 +225,8 @@ static bool SpriteImageExport(const rct_g1_element& spriteElement, const char* o
}
static std::optional<ImageImporter::ImportResult> 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<ImageImporter::ImportResult> SpriteImageImport(
flags = ImageImporter::IMPORT_FLAGS::RLE;
}
if (keep_palette)
if (palette == ImageImporter::PALETTE::KEEP_INDICES)
{
format = IMAGE_FORMAT::PNG;
flags = static_cast<ImageImporter::IMPORT_FLAGS>(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<ImageImporter::IMPORT_MODE>(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<int16_t>(x_offset), Json::GetNumber<int16_t>(y_offset), keep_palette,
forceBmp, gSpriteMode);
imagePath.c_str(), Json::GetNumber<int16_t>(x_offset), Json::GetNumber<int16_t>(y_offset), palette, forceBmp,
gSpriteMode);
if (importResult == std::nullopt)
{
fprintf(stderr, "Could not import image file: %s\nCanceling\n", imagePath.c_str());

View file

@ -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;

View file

@ -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<const char**>(argEnumerator->GetArguments()) + argEnumerator->GetIndex() - 1;

View file

@ -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<int32_t> 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<int32_t> buffer;
buffer.reserve(width * height);
@ -68,13 +68,13 @@ std::vector<int32_t> ImageImporter::GetPixels(
// A larger range is needed for proper dithering
auto palettedSrc = pixels;
std::unique_ptr<int16_t[]> rgbaSrcBuffer;
if (!(flags & IMPORT_FLAGS::KEEP_PALETTE))
if (palette != PALETTE::KEEP_INDICES)
{
rgbaSrcBuffer = std::make_unique<int16_t[]>(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<int32_t> 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++)

View file

@ -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<int32_t> 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<uint8_t> EncodeRaw(const int32_t* pixels, uint32_t width, uint32_t height);
static std::vector<uint8_t> EncodeRLE(const int32_t* pixels, uint32_t width, uint32_t height);

View file

@ -145,7 +145,8 @@ std::vector<std::unique_ptr<ImageTable::RequiredImage>> 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<RequiredImage>(importResult.Element));
}
@ -179,13 +180,14 @@ std::vector<std::unique_ptr<ImageTable::RequiredImage>> ImageTable::ParseImages(
try
{
auto flags = ImageImporter::IMPORT_FLAGS::NONE;
auto palette = ImageImporter::PALETTE::OPENRCT2;
if (!raw)
{
flags = static_cast<ImageImporter::IMPORT_FLAGS>(flags | ImageImporter::IMPORT_FLAGS::RLE);
}
if (keepPalette)
{
flags = static_cast<ImageImporter::IMPORT_FLAGS>(flags | ImageImporter::IMPORT_FLAGS::KEEP_PALETTE);
palette = ImageImporter::PALETTE::KEEP_INDICES;
}
auto itSource = std::find_if(
@ -204,7 +206,7 @@ std::vector<std::unique_ptr<ImageTable::RequiredImage>> 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<RequiredImage>(g1element));

View file

@ -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);