mirror of https://github.com/OpenRCT2/OpenRCT2.git
parent
53e8816881
commit
67a8d833ea
|
@ -244,9 +244,8 @@ static bool sprite_file_export(rct_g1_element* spriteHeader, const char* outPath
|
|||
}
|
||||
}
|
||||
|
||||
static bool sprite_file_import(
|
||||
const char* path, int16_t x_offset, int16_t y_offset, bool keep_palette, bool forceBmp, rct_g1_element* outElement,
|
||||
uint8_t** outBuffer, int* outBufferLength, int32_t mode)
|
||||
static std::optional<ImageImporter::ImportResult> sprite_file_import(
|
||||
const char* path, int16_t x_offset, int16_t y_offset, bool keep_palette, bool forceBmp, int32_t mode)
|
||||
{
|
||||
try
|
||||
{
|
||||
|
@ -266,17 +265,13 @@ static bool sprite_file_import(
|
|||
|
||||
ImageImporter importer;
|
||||
auto image = Imaging::ReadFromFile(path, format);
|
||||
auto result = importer.Import(image, x_offset, y_offset, flags, static_cast<ImageImporter::IMPORT_MODE>(mode));
|
||||
|
||||
*outElement = result.Element;
|
||||
*outBuffer = static_cast<uint8_t*>(result.Buffer);
|
||||
*outBufferLength = static_cast<int>(result.BufferLength);
|
||||
return true;
|
||||
return importer.Import(image, x_offset, y_offset, flags, static_cast<ImageImporter::IMPORT_MODE>(mode));
|
||||
}
|
||||
catch (const std::exception& e)
|
||||
{
|
||||
fprintf(stderr, "%s\n", e.what());
|
||||
return false;
|
||||
return std::nullopt;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -643,12 +638,8 @@ int32_t cmdline_for_sprite(const char** argv, int32_t argc)
|
|||
}
|
||||
}
|
||||
|
||||
rct_g1_element spriteElement;
|
||||
uint8_t* buffer;
|
||||
|
||||
int32_t bufferLength;
|
||||
if (!sprite_file_import(
|
||||
imagePath, x_offset, y_offset, false, false, &spriteElement, &buffer, &bufferLength, gSpriteMode))
|
||||
auto importResult = sprite_file_import(imagePath, x_offset, y_offset, false, false, gSpriteMode);
|
||||
if (importResult == std::nullopt)
|
||||
return -1;
|
||||
|
||||
if (!sprite_file_open(spriteFilePath))
|
||||
|
@ -658,7 +649,7 @@ int32_t cmdline_for_sprite(const char** argv, int32_t argc)
|
|||
}
|
||||
|
||||
spriteFileHeader.num_entries++;
|
||||
spriteFileHeader.total_size += bufferLength;
|
||||
spriteFileHeader.total_size += static_cast<uint32_t>(importResult->Buffer.size());
|
||||
spriteFileEntries = static_cast<rct_g1_element*>(
|
||||
realloc(spriteFileEntries, spriteFileHeader.num_entries * sizeof(rct_g1_element)));
|
||||
|
||||
|
@ -666,12 +657,13 @@ int32_t cmdline_for_sprite(const char** argv, int32_t argc)
|
|||
spriteFileData = static_cast<uint8_t*>(realloc(spriteFileData, spriteFileHeader.total_size));
|
||||
sprite_entries_make_absolute();
|
||||
|
||||
spriteFileEntries[spriteFileHeader.num_entries - 1] = spriteElement;
|
||||
std::memcpy(spriteFileData + (spriteFileHeader.total_size - bufferLength), buffer, bufferLength);
|
||||
spriteFileEntries[spriteFileHeader.num_entries - 1].offset = spriteFileData
|
||||
+ (spriteFileHeader.total_size - bufferLength);
|
||||
spriteFileEntries[spriteFileHeader.num_entries - 1] = importResult->Element;
|
||||
|
||||
const auto& buffer = importResult->Buffer;
|
||||
std::memcpy(spriteFileData + (spriteFileHeader.total_size - buffer.size()), buffer.data(), buffer.size());
|
||||
spriteFileEntries[spriteFileHeader.num_entries - 1].offset = spriteFileData
|
||||
+ (spriteFileHeader.total_size - buffer.size());
|
||||
|
||||
free(buffer);
|
||||
if (!sprite_file_save(spriteFilePath))
|
||||
return -1;
|
||||
|
||||
|
@ -768,14 +760,10 @@ int32_t cmdline_for_sprite(const char** argv, int32_t argc)
|
|||
// Resolve absolute sprite path
|
||||
auto imagePath = platform_get_absolute_path(json_string_value(path), directoryPath);
|
||||
|
||||
rct_g1_element spriteElement;
|
||||
uint8_t* buffer;
|
||||
int bufferLength;
|
||||
|
||||
if (!sprite_file_import(
|
||||
auto importResult = sprite_file_import(
|
||||
imagePath.c_str(), x_offset == nullptr ? 0 : json_integer_value(x_offset),
|
||||
y_offset == nullptr ? 0 : json_integer_value(y_offset), keep_palette, forceBmp, &spriteElement, &buffer,
|
||||
&bufferLength, gSpriteMode))
|
||||
y_offset == nullptr ? 0 : json_integer_value(y_offset), keep_palette, forceBmp, gSpriteMode);
|
||||
if (importResult == std::nullopt)
|
||||
{
|
||||
fprintf(stderr, "Could not import image file: %s\nCanceling\n", imagePath.c_str());
|
||||
json_decref(sprite_list);
|
||||
|
@ -790,7 +778,7 @@ int32_t cmdline_for_sprite(const char** argv, int32_t argc)
|
|||
}
|
||||
|
||||
spriteFileHeader.num_entries++;
|
||||
spriteFileHeader.total_size += bufferLength;
|
||||
spriteFileHeader.total_size += static_cast<uint32_t>(importResult->Buffer.size());
|
||||
spriteFileEntries = static_cast<rct_g1_element*>(
|
||||
realloc(spriteFileEntries, spriteFileHeader.num_entries * sizeof(rct_g1_element)));
|
||||
|
||||
|
@ -798,12 +786,12 @@ int32_t cmdline_for_sprite(const char** argv, int32_t argc)
|
|||
spriteFileData = static_cast<uint8_t*>(realloc(spriteFileData, spriteFileHeader.total_size));
|
||||
sprite_entries_make_absolute();
|
||||
|
||||
spriteFileEntries[spriteFileHeader.num_entries - 1] = spriteElement;
|
||||
std::memcpy(spriteFileData + (spriteFileHeader.total_size - bufferLength), buffer, bufferLength);
|
||||
spriteFileEntries[spriteFileHeader.num_entries - 1].offset = spriteFileData
|
||||
+ (spriteFileHeader.total_size - bufferLength);
|
||||
spriteFileEntries[spriteFileHeader.num_entries - 1] = importResult->Element;
|
||||
|
||||
free(buffer);
|
||||
const auto& buffer = importResult->Buffer;
|
||||
std::memcpy(spriteFileData + (spriteFileHeader.total_size - buffer.size()), buffer.data(), buffer.size());
|
||||
spriteFileEntries[spriteFileHeader.num_entries - 1].offset = spriteFileData
|
||||
+ (spriteFileHeader.total_size - buffer.size());
|
||||
|
||||
if (!sprite_file_save(spriteFilePath))
|
||||
{
|
||||
|
|
|
@ -37,11 +37,9 @@ ImportResult ImageImporter::Import(
|
|||
const auto height = image.Height;
|
||||
|
||||
auto pixels = GetPixels(image.Pixels.data(), width, height, flags, mode);
|
||||
auto [buffer, bufferLength] = flags & IMPORT_FLAGS::RLE ? EncodeRLE(pixels.data(), width, height)
|
||||
: EncodeRaw(pixels.data(), width, height);
|
||||
auto buffer = flags & IMPORT_FLAGS::RLE ? EncodeRLE(pixels.data(), width, height) : EncodeRaw(pixels.data(), width, height);
|
||||
|
||||
rct_g1_element outElement;
|
||||
outElement.offset = static_cast<uint8_t*>(buffer);
|
||||
outElement.width = width;
|
||||
outElement.height = height;
|
||||
outElement.flags = (flags & IMPORT_FLAGS::RLE ? G1_FLAG_RLE_COMPRESSION : G1_FLAG_BMP);
|
||||
|
@ -51,8 +49,8 @@ ImportResult ImageImporter::Import(
|
|||
|
||||
ImportResult result;
|
||||
result.Element = outElement;
|
||||
result.Buffer = buffer;
|
||||
result.BufferLength = bufferLength;
|
||||
result.Buffer = std::move(buffer);
|
||||
result.Element.offset = result.Buffer.data();
|
||||
return result;
|
||||
}
|
||||
|
||||
|
@ -108,19 +106,19 @@ std::vector<int32_t> ImageImporter::GetPixels(
|
|||
return buffer;
|
||||
}
|
||||
|
||||
std::tuple<void*, size_t> ImageImporter::EncodeRaw(const int32_t* pixels, uint32_t width, uint32_t height)
|
||||
std::vector<uint8_t> ImageImporter::EncodeRaw(const int32_t* pixels, uint32_t width, uint32_t height)
|
||||
{
|
||||
auto bufferLength = width * height;
|
||||
auto buffer = static_cast<uint8_t*>(std::malloc(bufferLength));
|
||||
std::vector<uint8_t> buffer(bufferLength);
|
||||
for (size_t i = 0; i < bufferLength; i++)
|
||||
{
|
||||
auto p = pixels[i];
|
||||
buffer[i] = (p == PALETTE_TRANSPARENT ? 0 : static_cast<uint8_t>(p));
|
||||
}
|
||||
return std::make_tuple(buffer, bufferLength);
|
||||
return buffer;
|
||||
}
|
||||
|
||||
std::tuple<void*, size_t> ImageImporter::EncodeRLE(const int32_t* pixels, uint32_t width, uint32_t height)
|
||||
std::vector<uint8_t> ImageImporter::EncodeRLE(const int32_t* pixels, uint32_t width, uint32_t height)
|
||||
{
|
||||
struct RLECode
|
||||
{
|
||||
|
@ -129,18 +127,14 @@ std::tuple<void*, size_t> ImageImporter::EncodeRLE(const int32_t* pixels, uint32
|
|||
};
|
||||
|
||||
auto src = pixels;
|
||||
auto buffer = static_cast<uint8_t*>(std::malloc((height * 2) + (width * height * 16)));
|
||||
if (buffer == nullptr)
|
||||
{
|
||||
throw std::bad_alloc();
|
||||
}
|
||||
std::vector<uint8_t> buffer((height * 2) + (width * height * 16));
|
||||
|
||||
std::fill_n(buffer, (height * 2) + (width * height * 16), 0x00);
|
||||
auto yOffsets = reinterpret_cast<uint16_t*>(buffer);
|
||||
auto dst = buffer + (height * 2);
|
||||
std::fill_n(buffer.data(), (height * 2) + (width * height * 16), 0x00);
|
||||
auto yOffsets = reinterpret_cast<uint16_t*>(buffer.data());
|
||||
auto dst = buffer.data() + (height * 2);
|
||||
for (uint32_t y = 0; y < height; y++)
|
||||
{
|
||||
yOffsets[y] = static_cast<uint16_t>(dst - buffer);
|
||||
yOffsets[y] = static_cast<uint16_t>(dst - buffer.data());
|
||||
|
||||
auto previousCode = static_cast<RLECode*>(nullptr);
|
||||
auto currentCode = reinterpret_cast<RLECode*>(dst);
|
||||
|
@ -213,13 +207,9 @@ std::tuple<void*, size_t> ImageImporter::EncodeRLE(const int32_t* pixels, uint32
|
|||
}
|
||||
}
|
||||
|
||||
auto bufferLength = static_cast<size_t>(dst - buffer);
|
||||
buffer = static_cast<uint8_t*>(realloc(buffer, bufferLength));
|
||||
if (buffer == nullptr)
|
||||
{
|
||||
throw std::bad_alloc();
|
||||
}
|
||||
return std::make_tuple(buffer, bufferLength);
|
||||
auto bufferLength = static_cast<size_t>(dst - buffer.data());
|
||||
buffer.resize(bufferLength);
|
||||
return buffer;
|
||||
}
|
||||
|
||||
int32_t ImageImporter::CalculatePaletteIndex(
|
||||
|
|
|
@ -28,8 +28,7 @@ namespace OpenRCT2::Drawing
|
|||
struct ImportResult
|
||||
{
|
||||
rct_g1_element Element{};
|
||||
void* Buffer{};
|
||||
size_t BufferLength{};
|
||||
std::vector<uint8_t> Buffer;
|
||||
};
|
||||
|
||||
enum class IMPORT_MODE
|
||||
|
@ -53,8 +52,8 @@ namespace OpenRCT2::Drawing
|
|||
private:
|
||||
static std::vector<int32_t> GetPixels(
|
||||
const uint8_t* pixels, uint32_t width, uint32_t height, IMPORT_FLAGS flags, IMPORT_MODE mode);
|
||||
static std::tuple<void*, size_t> EncodeRaw(const int32_t* pixels, uint32_t width, uint32_t height);
|
||||
static std::tuple<void*, size_t> EncodeRLE(const int32_t* pixels, uint32_t width, uint32_t height);
|
||||
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);
|
||||
|
||||
static int32_t CalculatePaletteIndex(
|
||||
IMPORT_MODE mode, int16_t* rgbaSrc, int32_t x, int32_t y, int32_t width, int32_t height);
|
||||
|
|
|
@ -414,7 +414,6 @@ namespace ObjectJsonHelpers
|
|||
auto importResult = importer.Import(image, 0, 0, ImageImporter::IMPORT_FLAGS::RLE);
|
||||
|
||||
result.push_back(std::make_unique<RequiredImage>(importResult.Element));
|
||||
std::free(importResult.Buffer);
|
||||
}
|
||||
catch (const std::exception& e)
|
||||
{
|
||||
|
@ -450,7 +449,6 @@ namespace ObjectJsonHelpers
|
|||
g1Element.x_offset = x;
|
||||
g1Element.y_offset = y;
|
||||
result.push_back(std::make_unique<RequiredImage>(g1Element));
|
||||
std::free(importResult.Buffer);
|
||||
}
|
||||
catch (const std::exception& e)
|
||||
{
|
||||
|
|
|
@ -43,7 +43,7 @@ TEST_F(ImageImporterTests, Import_Logo)
|
|||
auto image = Imaging::ReadFromFile(logoPath, IMAGE_FORMAT::PNG_32);
|
||||
auto result = importer.Import(image, 3, 5, ImageImporter::IMPORT_FLAGS::RLE);
|
||||
|
||||
ASSERT_EQ(result.Buffer, result.Element.offset);
|
||||
ASSERT_EQ(result.Buffer.data(), result.Element.offset);
|
||||
ASSERT_EQ(128, result.Element.width);
|
||||
ASSERT_EQ(128, result.Element.height);
|
||||
ASSERT_EQ(3, result.Element.x_offset);
|
||||
|
@ -52,8 +52,7 @@ TEST_F(ImageImporterTests, Import_Logo)
|
|||
|
||||
// Check to ensure RLE data doesn't change unexpectedly.
|
||||
// Update expected hash if change is expected.
|
||||
ASSERT_NE(nullptr, result.Buffer);
|
||||
auto hash = GetHash(result.Buffer, result.BufferLength);
|
||||
ASSERT_NE(nullptr, result.Buffer.data());
|
||||
auto hash = GetHash(result.Buffer.data(), result.Buffer.size());
|
||||
ASSERT_EQ(0xCEF27C7D, hash);
|
||||
free(result.Buffer);
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue