From 2d34fe3972586d3295bf673a44d28e598c3b099b Mon Sep 17 00:00:00 2001 From: zrowny Date: Thu, 13 May 2021 18:08:21 -0400 Subject: [PATCH 1/5] Update description of palette colors in ImageImporter --- src/openrct2/drawing/ImageImporter.h | 52 ++++++++++++++++++++++------ 1 file changed, 42 insertions(+), 10 deletions(-) diff --git a/src/openrct2/drawing/ImageImporter.h b/src/openrct2/drawing/ImageImporter.h index e121414259..0e5507e33e 100644 --- a/src/openrct2/drawing/ImageImporter.h +++ b/src/openrct2/drawing/ImageImporter.h @@ -65,10 +65,10 @@ namespace OpenRCT2::Drawing } // namespace OpenRCT2::Drawing constexpr const GamePalette StandardPalette = { { - // 0 (unused) + // 0 (Unused/Transparent) { 0, 0, 0, 255 }, - // 1 - 9 (misc. e.g. font and water) + // 1 - 9 (Misc. e.g. font, water, chain lift) { 1, 1, 1, 255 }, { 2, 2, 2, 255 }, { 3, 3, 3, 255 }, @@ -79,7 +79,7 @@ constexpr const GamePalette StandardPalette = { { { 8, 8, 8, 255 }, { 9, 9, 9, 255 }, - // + // 10 - 21 (Grey) { 35, 35, 23, 255 }, { 51, 51, 35, 255 }, { 67, 67, 47, 255 }, @@ -92,6 +92,8 @@ constexpr const GamePalette StandardPalette = { { { 195, 195, 183, 255 }, { 219, 219, 211, 255 }, { 243, 243, 239, 255 }, + + // 22 - 33 (Olive) { 0, 47, 51, 255 }, { 0, 59, 63, 255 }, { 11, 75, 79, 255 }, @@ -104,6 +106,8 @@ constexpr const GamePalette StandardPalette = { { { 115, 191, 187, 255 }, { 139, 207, 203, 255 }, { 163, 227, 223, 255 }, + + // 34 - 45 (Light Brown) { 7, 43, 67, 255 }, { 11, 59, 87, 255 }, { 23, 75, 111, 255 }, @@ -116,6 +120,8 @@ constexpr const GamePalette StandardPalette = { { { 135, 199, 219, 255 }, { 163, 219, 231, 255 }, { 195, 239, 247, 255 }, + + // 46 - 57 (Yellow, also used for tertiary remap) { 0, 27, 71, 255 }, { 0, 43, 95, 255 }, { 0, 63, 119, 255 }, @@ -128,6 +134,8 @@ constexpr const GamePalette StandardPalette = { { { 95, 243, 255, 255 }, { 143, 251, 255, 255 }, { 195, 255, 255, 255 }, + + // 58 - 69 (Indian Red) { 0, 0, 35, 255 }, { 0, 0, 79, 255 }, { 7, 7, 95, 255 }, @@ -140,6 +148,8 @@ constexpr const GamePalette StandardPalette = { { { 127, 127, 215, 255 }, { 159, 159, 235, 255 }, { 191, 191, 255, 255 }, + + // 70 - 81 (Grass Green) { 19, 51, 27, 255 }, { 23, 63, 35, 255 }, { 31, 79, 47, 255 }, @@ -152,6 +162,8 @@ constexpr const GamePalette StandardPalette = { { { 83, 187, 147, 255 }, { 95, 203, 163, 255 }, { 103, 219, 183, 255 }, + + // 82 - 93 (Olive Green) { 27, 55, 31, 255 }, { 35, 71, 47, 255 }, { 43, 83, 59, 255 }, @@ -164,6 +176,8 @@ constexpr const GamePalette StandardPalette = { { { 147, 219, 195, 255 }, { 167, 231, 207, 255 }, { 191, 247, 223, 255 }, + + // 94 - 105 (Green) { 0, 63, 15, 255 }, { 0, 83, 19, 255 }, { 0, 103, 23, 255 }, @@ -176,6 +190,8 @@ constexpr const GamePalette StandardPalette = { { { 115, 223, 139, 255 }, { 143, 239, 163, 255 }, { 179, 255, 195, 255 }, + + // 106 - 117 (Tan) { 19, 43, 79, 255 }, { 27, 55, 99, 255 }, { 43, 71, 119, 255 }, @@ -188,6 +204,8 @@ constexpr const GamePalette StandardPalette = { { { 151, 191, 239, 255 }, { 171, 207, 247, 255 }, { 195, 227, 255, 255 }, + + // 118 - 129 (Indigo) { 55, 19, 15, 255 }, { 87, 43, 39, 255 }, { 103, 55, 51, 255 }, @@ -200,6 +218,8 @@ constexpr const GamePalette StandardPalette = { { { 223, 183, 183, 255 }, { 239, 211, 211, 255 }, { 255, 239, 239, 255 }, + + // 130 - 141 (Blue) { 111, 27, 0, 255 }, { 151, 39, 0, 255 }, { 167, 51, 7, 255 }, @@ -212,6 +232,8 @@ constexpr const GamePalette StandardPalette = { { { 243, 211, 143, 255 }, { 251, 231, 175, 255 }, { 255, 247, 215, 255 }, + + // 142 - 153 (Sea Green) { 15, 43, 11, 255 }, { 23, 55, 15, 255 }, { 31, 71, 23, 255 }, @@ -224,6 +246,8 @@ constexpr const GamePalette StandardPalette = { { { 167, 199, 147, 255 }, { 195, 219, 175, 255 }, { 223, 243, 207, 255 }, + + // 154 - 165 (Purple) { 95, 0, 63, 255 }, { 115, 7, 75, 255 }, { 127, 15, 83, 255 }, @@ -236,6 +260,8 @@ constexpr const GamePalette StandardPalette = { { { 231, 155, 191, 255 }, { 243, 195, 215, 255 }, { 255, 235, 243, 255 }, + + // 166 - 177 (Red) { 0, 0, 63, 255 }, { 0, 0, 87, 255 }, { 0, 0, 115, 255 }, @@ -248,6 +274,8 @@ constexpr const GamePalette StandardPalette = { { { 115, 123, 255, 255 }, { 163, 171, 255, 255 }, { 215, 219, 255, 255 }, + + // 178 - 189 (Orange) { 0, 39, 79, 255 }, { 0, 51, 111, 255 }, { 0, 63, 147, 255 }, @@ -260,6 +288,8 @@ constexpr const GamePalette StandardPalette = { { { 107, 183, 255, 255 }, { 135, 203, 255, 255 }, { 163, 219, 255, 255 }, + + // 190 - 201 (Water Blue) { 47, 51, 0, 255 }, { 55, 63, 0, 255 }, { 67, 75, 0, 255 }, @@ -273,7 +303,7 @@ constexpr const GamePalette StandardPalette = { { { 231, 231, 171, 255 }, { 255, 255, 207, 255 }, - // 202 - 213 (Secondary remap) + // 202 - 213 (Pink, also used for secondary remap) { 27, 0, 63, 255 }, { 51, 0, 103, 255 }, { 63, 11, 123, 255 }, @@ -301,27 +331,29 @@ constexpr const GamePalette StandardPalette = { { { 195, 219, 231, 255 }, { 223, 243, 255, 255 }, - // 226 (unknown) + // 226 (Extra grey) { 75, 75, 55, 255 }, - // 227 - 229 (tertiary remap) + // 227 - 229 (Extra yellows) { 0, 183, 255, 255 }, { 0, 219, 255, 255 }, { 0, 255, 255, 255 }, - // 230 - 239 (water) + // 230 - 234 (Water waves) { 99, 107, 7, 255 }, { 99, 107, 7, 255 }, { 135, 143, 39, 255 }, { 123, 131, 27, 255 }, { 99, 107, 7, 255 }, + + // 235 - 249 (Water sparkles) { 151, 155, 55, 255 }, { 151, 155, 55, 255 }, { 227, 227, 155, 255 }, { 203, 203, 115, 255 }, { 151, 155, 55, 255 }, - // 240 - 242 (chain lift) + // 240 - 242 (Exra grey) { 91, 91, 67, 255 }, { 107, 107, 83, 255 }, { 123, 123, 99, 255 }, @@ -331,7 +363,7 @@ constexpr const GamePalette StandardPalette = { { // { 47, 47, 47, 255 }, // { 47, 71, 87, 255 }, - // 243 to 254 (primary remap) + // 243 to 254 (Primary remap) { 47, 51, 111, 255 }, { 47, 55, 131, 255 }, { 51, 63, 151, 255 }, @@ -345,6 +377,6 @@ constexpr const GamePalette StandardPalette = { { { 63, 183, 255, 255 }, { 75, 207, 255, 255 }, - // 255 (unused?) + // 255 (Used in a small number of cases for pure white) { 0, 0, 0, 255 }, } }; From c4aaae1a07bb2106f4fc23748aef9b520b309577 Mon Sep 17 00:00:00 2001 From: zrowny Date: Thu, 13 May 2021 18:21:44 -0400 Subject: [PATCH 2/5] Correct ImageImporter palette index 255 to white Reflects the change that was made in 5035492f8cf93a03eac799a92f8cb30df2bb3ed9 to the renderer to fix #1749 and #6535 --- src/openrct2/drawing/ImageImporter.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/openrct2/drawing/ImageImporter.h b/src/openrct2/drawing/ImageImporter.h index 0e5507e33e..def6288f39 100644 --- a/src/openrct2/drawing/ImageImporter.h +++ b/src/openrct2/drawing/ImageImporter.h @@ -378,5 +378,5 @@ constexpr const GamePalette StandardPalette = { { { 75, 207, 255, 255 }, // 255 (Used in a small number of cases for pure white) - { 0, 0, 0, 255 }, + { 255, 255, 255, 255 }, } }; From c381a97d66e251accc6f335e41feeccda9f71a65 Mon Sep 17 00:00:00 2001 From: zrowny Date: Thu, 13 May 2021 20:54:06 -0400 Subject: [PATCH 3/5] Fix ImageImporter for colors outside of palette (#14649:) When converting to the internal palette, if a color is not in the palette, the ImageImporter now re-maps it only to those non "special" color indices ("special," meaning those for water effects, font, chain lift and so on, as well as the primary remappable color). Additionally, if the Importer is told to dither the image, it now does not dither colors that are already in the OpenRCT2 palette, or dither between remappable colors and non-remappable colors. --- src/openrct2/drawing/ImageImporter.cpp | 73 ++++++++++++++++---------- src/openrct2/drawing/ImageImporter.h | 15 +++++- 2 files changed, 58 insertions(+), 30 deletions(-) diff --git a/src/openrct2/drawing/ImageImporter.cpp b/src/openrct2/drawing/ImageImporter.cpp index fe7b313872..c447a0c3fc 100644 --- a/src/openrct2/drawing/ImageImporter.cpp +++ b/src/openrct2/drawing/ImageImporter.cpp @@ -217,24 +217,22 @@ int32_t ImageImporter::CalculatePaletteIndex( { auto& palette = StandardPalette; auto paletteIndex = GetPaletteIndex(palette, rgbaSrc); - if (mode == IMPORT_MODE::CLOSEST || mode == IMPORT_MODE::DITHERING) + if ((mode == IMPORT_MODE::CLOSEST || mode == IMPORT_MODE::DITHERING) && !IsInPalette(palette, rgbaSrc)) { - if (paletteIndex == PALETTE_TRANSPARENT && !IsTransparentPixel(rgbaSrc)) - { - paletteIndex = GetClosestPaletteIndex(palette, rgbaSrc); - } - } - if (mode == IMPORT_MODE::DITHERING) - { - if (!IsTransparentPixel(rgbaSrc) && IsChangablePixel(GetPaletteIndex(palette, rgbaSrc))) + paletteIndex = GetClosestPaletteIndex(palette, rgbaSrc); + if (mode == IMPORT_MODE::DITHERING) { auto dr = rgbaSrc[0] - static_cast(palette[paletteIndex].Red); auto dg = rgbaSrc[1] - static_cast(palette[paletteIndex].Green); auto db = rgbaSrc[2] - static_cast(palette[paletteIndex].Blue); + // We don't want to dither remappable colors with nonremappable colors, etc + PaletteIndexType thisIndexType = GetPaletteIndexType(paletteIndex); + if (x + 1 < width) { - if (!IsTransparentPixel(rgbaSrc + 4) && IsChangablePixel(GetPaletteIndex(palette, rgbaSrc + 4))) + if (!IsInPalette(palette, rgbaSrc + 4) + && thisIndexType == GetPaletteIndexType(GetClosestPaletteIndex(palette, rgbaSrc + 4))) { // Right rgbaSrc[4] += dr * 7 / 16; @@ -247,8 +245,8 @@ int32_t ImageImporter::CalculatePaletteIndex( { if (x > 0) { - if (!IsTransparentPixel(rgbaSrc + 4 * (width - 1)) - && IsChangablePixel(GetPaletteIndex(palette, rgbaSrc + 4 * (width - 1)))) + if (!IsInPalette(palette, rgbaSrc + 4 * (width - 1)) + && thisIndexType == GetPaletteIndexType(GetClosestPaletteIndex(palette, rgbaSrc + 4 * (width - 1)))) { // Bottom left rgbaSrc[4 * (width - 1)] += dr * 3 / 16; @@ -258,7 +256,8 @@ int32_t ImageImporter::CalculatePaletteIndex( } // Bottom - if (!IsTransparentPixel(rgbaSrc + 4 * width) && IsChangablePixel(GetPaletteIndex(palette, rgbaSrc + 4 * width))) + if (!IsInPalette(palette, rgbaSrc + 4 * width) + && thisIndexType == GetPaletteIndexType(GetClosestPaletteIndex(palette, rgbaSrc + 4 * width))) { rgbaSrc[4 * width] += dr * 5 / 16; rgbaSrc[4 * width + 1] += dg * 5 / 16; @@ -267,8 +266,8 @@ int32_t ImageImporter::CalculatePaletteIndex( if (x + 1 < width) { - if (!IsTransparentPixel(rgbaSrc + 4 * (width + 1)) - && IsChangablePixel(GetPaletteIndex(palette, rgbaSrc + 4 * (width + 1)))) + if (!IsInPalette(palette, rgbaSrc + 4 * (width + 1)) + && thisIndexType == GetPaletteIndexType(GetClosestPaletteIndex(palette, rgbaSrc + 4 * (width + 1)))) { // Bottom right rgbaSrc[4 * (width + 1)] += dr * 1 / 16; @@ -279,6 +278,7 @@ int32_t ImageImporter::CalculatePaletteIndex( } } } + return paletteIndex; } @@ -304,23 +304,40 @@ bool ImageImporter::IsTransparentPixel(const int16_t* colour) } /** - * @returns true if pixel index is an index not used for remapping. + * @returns true if this colour is in the standard palette. + */ +bool ImageImporter::IsInPalette(const GamePalette& palette, int16_t* colour) +{ + return !(GetPaletteIndex(palette, colour) == PALETTE_TRANSPARENT && !IsTransparentPixel(colour)); +} + +/** + * @returns true if palette index is an index not used for a special purpose. */ bool ImageImporter::IsChangablePixel(int32_t paletteIndex) { - if (paletteIndex == PALETTE_TRANSPARENT) - return true; - if (paletteIndex == 0) - return false; + PaletteIndexType entryType = GetPaletteIndexType(paletteIndex); + return entryType != PaletteIndexType::Special && entryType != PaletteIndexType::PrimaryRemap; +} + +/** + * @returns the type of palette entry this is. + */ +ImageImporter::PaletteIndexType ImageImporter::GetPaletteIndexType(int32_t paletteIndex) +{ + if (paletteIndex <= 9) + return PaletteIndexType::Special; + if (paletteIndex >= 230 && paletteIndex <= 239) + return PaletteIndexType::Special; + if (paletteIndex == 255) + return PaletteIndexType::Special; + if (paletteIndex >= 243 && paletteIndex <= 254) + return PaletteIndexType::PrimaryRemap; if (paletteIndex >= 202 && paletteIndex <= 213) - return false; - if (paletteIndex == 226) - return false; - if (paletteIndex >= 227 && paletteIndex <= 229) - return false; - if (paletteIndex >= 243) - return false; - return true; + return PaletteIndexType::SecondaryRemap; + if (paletteIndex >= 46 && paletteIndex <= 57) + return PaletteIndexType::TertiaryRemap; + return PaletteIndexType::Normal; } int32_t ImageImporter::GetClosestPaletteIndex(const GamePalette& palette, const int16_t* colour) diff --git a/src/openrct2/drawing/ImageImporter.h b/src/openrct2/drawing/ImageImporter.h index def6288f39..70e61b046f 100644 --- a/src/openrct2/drawing/ImageImporter.h +++ b/src/openrct2/drawing/ImageImporter.h @@ -50,6 +50,15 @@ namespace OpenRCT2::Drawing IMPORT_MODE mode = IMPORT_MODE::DEFAULT) const; private: + enum class PaletteIndexType : uint8_t + { + Normal, + PrimaryRemap, + SecondaryRemap, + TertiaryRemap, + Special, + }; + static std::vector GetPixels( const uint8_t* pixels, uint32_t width, uint32_t height, IMPORT_FLAGS flags, IMPORT_MODE mode); static std::vector EncodeRaw(const int32_t* pixels, uint32_t width, uint32_t height); @@ -59,7 +68,9 @@ namespace OpenRCT2::Drawing IMPORT_MODE mode, int16_t* rgbaSrc, int32_t x, int32_t y, int32_t width, int32_t height); static int32_t GetPaletteIndex(const GamePalette& palette, int16_t* colour); static bool IsTransparentPixel(const int16_t* colour); + static bool IsInPalette(const GamePalette& palette, int16_t* colour); static bool IsChangablePixel(int32_t paletteIndex); + static PaletteIndexType GetPaletteIndexType(int32_t paletteIndex); static int32_t GetClosestPaletteIndex(const GamePalette& palette, const int16_t* colour); }; } // namespace OpenRCT2::Drawing @@ -176,7 +187,7 @@ constexpr const GamePalette StandardPalette = { { { 147, 219, 195, 255 }, { 167, 231, 207, 255 }, { 191, 247, 223, 255 }, - + // 94 - 105 (Green) { 0, 63, 15, 255 }, { 0, 83, 19, 255 }, @@ -353,7 +364,7 @@ constexpr const GamePalette StandardPalette = { { { 203, 203, 115, 255 }, { 151, 155, 55, 255 }, - // 240 - 242 (Exra grey) + // 240 - 242 (Extra grey) { 91, 91, 67, 255 }, { 107, 107, 83, 255 }, { 123, 123, 99, 255 }, From fa0efd67c14f228055401f4c319f1257d2979b91 Mon Sep 17 00:00:00 2001 From: Gymnasiast Date: Sun, 5 Sep 2021 20:38:33 +0200 Subject: [PATCH 4/5] Update changelog --- distribution/changelog.txt | 1 + 1 file changed, 1 insertion(+) diff --git a/distribution/changelog.txt b/distribution/changelog.txt index a800039df6..13c0ca1a18 100644 --- a/distribution/changelog.txt +++ b/distribution/changelog.txt @@ -10,6 +10,7 @@ - Feature: [#15294] New vehicle animation type: flying animal. - Fix: [#13465] Creating a scenario based on a won save game results in a scenario that’s instantly won. - Fix: [#14316] Closing the Track Designs Manager window causes broken state. +- Fix: [#14649] ImageImporter incorrectly remaps colours outside the RCT2 palette. - Fix: [#14667] “Extreme Hawaiian Island” has unpurchaseable land tiles (original bug). - Fix: [#15096] Crash when placing entrances in the scenario editor near the map corner. - Fix: [#15142] ToonTowner's mine roofs were moved into the pirate theme scenery group instead of the mine theme scenery group. From e26c4bdd4e0b0d2447f69d2000935dd623014f62 Mon Sep 17 00:00:00 2001 From: Gymnasiast Date: Sun, 5 Sep 2021 20:40:01 +0200 Subject: [PATCH 5/5] Fix US spelling --- src/openrct2/drawing/ImageImporter.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/openrct2/drawing/ImageImporter.cpp b/src/openrct2/drawing/ImageImporter.cpp index c447a0c3fc..3f578faf49 100644 --- a/src/openrct2/drawing/ImageImporter.cpp +++ b/src/openrct2/drawing/ImageImporter.cpp @@ -226,7 +226,7 @@ int32_t ImageImporter::CalculatePaletteIndex( auto dg = rgbaSrc[1] - static_cast(palette[paletteIndex].Green); auto db = rgbaSrc[2] - static_cast(palette[paletteIndex].Blue); - // We don't want to dither remappable colors with nonremappable colors, etc + // We don't want to dither remappable colours with nonremappable colours, etc PaletteIndexType thisIndexType = GetPaletteIndexType(paletteIndex); if (x + 1 < width)