Agrarsense
ColorUtilities.cpp
Go to the documentation of this file.
1// Copyright (c) 2023 FrostBit Software Lab at the Lapland University of Applied Sciences
2//
3// This work is licensed under the terms of the MIT license.
4// For a copy, see <https://opensource.org/licenses/MIT>.
5
6#include "ColorUtilities.h"
7#include "Misc/DefaultValueHelper.h"
8
9FLinearColor UColorUtilities::HexToLinearColor(const FString& HexString, bool& bSuccess)
10{
11
12 if (IsValidHexString(HexString))
13 {
14 bSuccess = true;
15 /*
16 Creates a color value from the given hexadecimal string.
17 Supported formats are: RGB, RRGGBB, RRGGBBAA, RGB, #RRGGBB, #RRGGBBAA The corresponding color value.
18 */
19 FColor Color = FColor::FromHex(HexString);
20 return Color.ReinterpretAsLinear();
21 }
22 else
23 {
24 UE_LOG(LogTemp, Warning, TEXT("Invalid Hex String Format: %s"), *HexString);
25 bSuccess = false;
26 return FLinearColor::White;
27 }
28
29 // FString CleanHex = HexString.Replace(TEXT("#"), TEXT("")); // Remove #
30
31 // if (CleanHex.Len() != 6 && CleanHex.Len() != 8)
32 //{
33 // UE_LOG(LogTemp, Warning, TEXT("Invalid Hex Color Length: %s"), *HexString);
34 // return FLinearColor::White;
35 // }
36
37 // int32 R, G, B, A = 255; // Default alpha to 255
38
40 // FDefaultValueHelper::ParseInt(CleanHex.Mid(0, 2), R, 16);
41 // FDefaultValueHelper::ParseInt(CleanHex.Mid(2, 2), G, 16);
42 // FDefaultValueHelper::ParseInt(CleanHex.Mid(4, 2), B, 16);
43
44 // if (CleanHex.Len() == 8)
45 //{
46 // FDefaultValueHelper::ParseInt(CleanHex.Mid(6, 2), A, 16);
47 // }
48
49 // return FLinearColor(R / 255.0f, G / 255.0f, B / 255.0f, A / 255.0f);
50}
51
52FLinearColor UColorUtilities::RGBStringToLinearColor(const FString& ColorString, bool& bSuccess)
53{
54 if (IsValidRGBString(ColorString))
55 {
56 bSuccess = true;
57 TArray<FString> Components;
58 ColorString.ParseIntoArray(Components, TEXT(","), true);
59
60 int32 R = 0, G = 0, B = 0, A = 255; // Default alpha to 255 (fully opaque)
61
62 // Parse integer values from the string components
63 FDefaultValueHelper::ParseInt(Components[0], R);
64 FDefaultValueHelper::ParseInt(Components[1], G);
65 FDefaultValueHelper::ParseInt(Components[2], B);
66
67 if (Components.Num() == 4) // If alpha is provided
68 {
69 FDefaultValueHelper::ParseInt(Components[3], A);
70 }
71
72 // Convert to linear color
73 return FLinearColor(R / 255.0f, G / 255.0f, B / 255.0f, A / 255.0f);
74 }
75
76 // Invalid string format
77 bSuccess = false;
78 UE_LOG(LogTemp, Warning, TEXT("Invalid Color String Format: %s"), *ColorString);
79 return FLinearColor::White;
80}
81
82FString UColorUtilities::LinearColorToHex(const FLinearColor& Color, bool bIncludeAlpha, bool bAddPrefix)
83{
84 FColor ConvertedColor = Color.Quantize(); // Converts FLinearColor to FColor
85 FString HexString = ConvertedColor.ToHex(); // Returns RRGGBBAA format
86
87 if (!bIncludeAlpha)
88 {
89 HexString = HexString.Left(6); // Trim the last two characters (AA)
90 }
91
92 if (bAddPrefix)
93 {
94 HexString = FString("#") + HexString;
95 }
96
97 return HexString;
98
99 // int32 R = FMath::RoundToInt(Color.R * 255);
100 // int32 G = FMath::RoundToInt(Color.G * 255);
101 // int32 B = FMath::RoundToInt(Color.B * 255);
102 // int32 A = FMath::RoundToInt(Color.A * 255);
103
104 // FString HexString = FString::Printf(TEXT("#%02X%02X%02X"), R, G, B);
105
106 // if (bIncludeAlpha)
107 //{
108 // HexString += FString::Printf(TEXT("%02X"), A);
109 // }
110
111 // return HexString;
112}
113
114FString UColorUtilities::LinearColorToRGBString(const FLinearColor& Color, bool bIncludeAlpha)
115{
116 int32 R = FMath::RoundToInt(Color.R * 255);
117 int32 G = FMath::RoundToInt(Color.G * 255);
118 int32 B = FMath::RoundToInt(Color.B * 255);
119 int32 A = FMath::RoundToInt(Color.A * 255);
120
121 if (bIncludeAlpha)
122 {
123 return FString::Printf(TEXT("%d,%d,%d,%d"), R, G, B, A);
124 }
125 else
126 {
127 return FString::Printf(TEXT("%d,%d,%d"), R, G, B);
128 }
129}
130
131bool UColorUtilities::IsValidRGBString(const FString& ColorString)
132{
133 FString TrimmedString = ColorString.TrimStartAndEnd(); // Remove whitespace
134 TArray<FString> Components;
135 TrimmedString.ParseIntoArray(Components, TEXT(","), true);
136
137 // RGB(A) must have 3 or 4 integer values
138 if (Components.Num() < 3 || Components.Num() > 4)
139 {
140 return false;
141 }
142
143 for (const FString& Component : Components)
144 {
145 int32 Value;
146 if (!FDefaultValueHelper::ParseInt(Component, Value) || Value < 0 || Value > 255)
147 {
148 return false; // Must be an integer between 0-255
149 }
150 }
151
152 return true; // Valid RGB or RGBA format
153}
154
155bool UColorUtilities::IsValidHexString(const FString& ColorString)
156{
157 FString TrimmedString = ColorString.TrimStartAndEnd().Replace(TEXT("#"), TEXT("")); // Remove '#' if present
158
159 // Must be exactly 6 (RRGGBB) or 8 (RRGGBBAA) characters long, shorthand (RGB) not supported
160 if (TrimmedString.Len() != 6 && TrimmedString.Len() != 8)
161 {
162 return false;
163 }
164
165 // Ensure all characters are valid hex digits (0-9, A-F, a-f)
166 for (TCHAR Char : TrimmedString)
167 {
168 if (!FChar::IsHexDigit(Char))
169 {
170 return false;
171 }
172 }
173
174 return true; // Valid hex format
175}
176
177FLinearColor UColorUtilities::AutoDetectColorStringToLinearColor(const FString& ColorString, bool& bSuccess)
178{
179 FString TrimmedString = ColorString.TrimStartAndEnd(); // Remove leading/trailing spaces
180 FLinearColor ConvertedColor;
181
182 // First try to convert string to linear color assuming it's rgb
183 ConvertedColor = RGBStringToLinearColor(TrimmedString, bSuccess);
184
185 // If that fails, assume it's hex
186 if (!bSuccess)
187 {
188 ConvertedColor = HexToLinearColor(TrimmedString, bSuccess);
189 }
190
191 // return converted color (and bSuccess). ConvertedColor set to FLinearColor::White if conversion failed in previous steps
192 return ConvertedColor;
193}
static bool IsValidRGBString(const FString &ColorString)
static FLinearColor HexToLinearColor(const FString &HexString, bool &bSuccess)
Converts a hex color code (e.g. "#FF00FF" or "#FF00FFAA" or "FF00FF" or "FF00FFAA) to an FLinearColor...
static FString LinearColorToHex(const FLinearColor &Color, bool bIncludeAlpha, bool bAddPrefix)
static FLinearColor RGBStringToLinearColor(const FString &ColorString, bool &bSuccess)
Converts a comma-separated color string ("r,g,b" or "r,g,b,a") to an FLinearColor.
static FLinearColor AutoDetectColorStringToLinearColor(const FString &ColorString, bool &bSuccess)
Tries to auto detect format for color string, and convert it to linear color accordingly.
static bool IsValidHexString(const FString &ColorString)
static FString LinearColorToRGBString(const FLinearColor &Color, bool bIncludeAlpha)