Arma Reforger Explorer 1.7.0.54
Arma Reforger Code Explorer by Zeroy - Thanks to MisterOutofTime
Loading...
Searching...
No Matches
SCR_HeatmapHelper.c
Go to the documentation of this file.
2{
3
4 static const int COLOUR_MODE_GREYSCALE = 0;
5 static const int COLOUR_MODE_THERMAL = 1;
6 static const int COLOUR_MODE_ALPHA = 2;
7
8 static const int MAX_MODE_RAW = 0;
9 static const int MAX_MODE_2AVG = 1;
10 static const int MAX_MODE_2MEDIAN = 2;
11
12 static const int MAX_RESOLUTION = 8192;
13
14 protected static const int MIN_GRADIENT_RGB = 8;
15
16 //------------------------------------------------------------------------------------------------
25 // TODO: maxRaw/maxAvg/maxMedian here
26 static bool CreateHeatmapImageFromData(string imagePath, notnull array<int> imageData, int colourMode = COLOUR_MODE_GREYSCALE, bool invertColour = false, int maxValueMode = MAX_MODE_RAW, bool highlightValuesAboveMax = false, int resolutionFactor = 1)
27 {
28 int imageDataCount = imageData.Count();
29 float resolution = Math.Sqrt(imageDataCount);
30 if (resolution != (int)resolution)
31 {
32 int idealResolution = Math.Round(resolution);
33 if (idealResolution < 1)
34 idealResolution = 1;
35
36 PrintFormat("Invalid image data: resolution is not square (√%1 ≈ %2, expected a perfect int e.g %3×%3 = %4)", imageDataCount, resolution, idealResolution, idealResolution * idealResolution, level: LogLevel.ERROR);
37 return false;
38 }
39
40 int maxToUse;
41 if (maxValueMode == MAX_MODE_2AVG)
42 {
43 Debug.BeginTimeMeasure();
44
45 int maxAvg;
46 int div;
47 foreach (int value : imageData)
48 {
49 if (value > 0)
50 {
51 maxAvg += value;
52 ++div;
53 }
54 }
55
56 if (div > 0)
57 maxToUse = 2 * maxAvg / div;
58
59 Debug.EndTimeMeasure("Defining average");
60 }
61 else
62 if (maxValueMode == MAX_MODE_2MEDIAN)
63 {
64 Debug.BeginTimeMeasure();
65
66 array<int> sortedValues = {};
67 sortedValues.Reserve(resolution * resolution); // at best
68 foreach (int index, int value : imageData)
69 {
70 if (value > 0)
71 sortedValues.Insert(value);
72 }
73
74 sortedValues.Sort();
75 maxToUse = sortedValues[sortedValues.Count() * 0.5] * 2;
76
77 Debug.EndTimeMeasure("Defining median");
78 }
79
80 if (maxToUse <= 0) // raw
81 {
82 Debug.BeginTimeMeasure();
83
84 foreach (int value : imageData)
85 {
86 if (value > maxToUse)
87 maxToUse = value;
88 }
89
90 Debug.EndTimeMeasure("Defining raw max");
91 }
92
93 if (maxToUse < MIN_GRADIENT_RGB && colourMode == COLOUR_MODE_THERMAL)
94 PrintFormat("Less than max %1 values per pixel, thermal gradient quality may be poor", MIN_GRADIENT_RGB, level: LogLevel.WARNING);
95
96
97 Debug.BeginTimeMeasure();
98
99 int colour;
100 float intensity01;
101 int iIntensity;
102 foreach (int index, int value : imageData)
103 {
104 if (value > 0) // faster?
105 intensity01 = (float)value / maxToUse;
106 else
107 intensity01 = 0;
108
109 if (colourMode == COLOUR_MODE_GREYSCALE)
110 {
111 iIntensity = Math.Round(intensity01 * 255);
112
113 // let's clamp
114 if (iIntensity > 255)
115 {
116 if (highlightValuesAboveMax)
117 colour = 0xFFFF0000; // red
118 else
119 colour = 0xFFFFFFFF; // white
120 }
121 else
122 if (iIntensity <= 0)
123 {
124 if (invertColour)
125 colour = 0xFFFFFFFF;
126 else
127 colour = 0xFF000000;
128 }
129 else
130 {
131 if (invertColour)
132 iIntensity = 255 - iIntensity;
133
134 colour = 0xFF000000
135 | (iIntensity << 16)
136 | (iIntensity << 8)
137 | iIntensity; // << 0
138 }
139 }
140 else
141 if (colourMode == COLOUR_MODE_THERMAL)
142 {
143 // based on https://stackoverflow.com/questions/7706339/grayscale-to-red-green-blue-matlab-jet-color-scale
144 if (intensity01 > 1)
145 {
146 if (highlightValuesAboveMax)
147 colour = 0xFFFFFFFF; // white
148 else
149 colour = 0xFFFF0000; // red
150 }
151 else
152 if (intensity01 <= 0)
153 {
154 if (invertColour)
155 colour = 0xFFFF0000; // red
156 else
157 colour = 0xFF000000; // black
158 }
159 else
160 {
161 if (invertColour)
162 intensity01 = 1 - intensity01;
163
164 float r, g, b;
165 if (intensity01 < 0.25)
166 {
167 // r = 0;
168 g = 4 * intensity01;
169 b = 1;
170 }
171 else
172 if (intensity01 < 0.5)
173 {
174 // r = 0;
175 g = 1;
176 b = 1 + 4 * (0.25 - intensity01);
177 }
178 else
179 if (intensity01 < 0.75)
180 {
181 r = 4 * (intensity01 - 0.5);
182 g = 1;
183 // b = 0;
184 }
185 else
186 {
187 r = 1;
188 g = 1 + 4 * (0.75 - intensity01);
189 // b = 0;
190 }
191
192 colour = 0xFF000000
193 | ((int)(255 * r) << 16)
194 | ((int)(255 * g) << 8)
195 | ((int)(255 * b)); // << 0
196 }
197 }
198 else
199// if (colourMode == COLOUR_MODE_ALPHA)
200 {
201 iIntensity = Math.Round(intensity01 * 255);
202
203 // let's clamp
204 if (iIntensity > 255)
205 {
206 if (highlightValuesAboveMax)
207 colour = 0xFFFF0000; // red
208 else
209 colour = 0xFFFFFFFF; // white
210 }
211 else
212 if (iIntensity <= 0)
213 {
214 if (invertColour)
215 colour = 0x00000000;
216 else
217 colour = 0x00FFFFFF;
218 }
219 else
220 {
221 if (invertColour)
222 colour = 0x00000000 | (iIntensity << 24);
223 else
224 colour = 0x00FFFFFF | (iIntensity << 24);
225 }
226 }
227
228 imageData[index] = colour;
229 }
230
231 Debug.EndTimeMeasure(string.Format("Setting pixel values for %1×%1 image", resolution, resolution));
232
233 if (resolutionFactor < 1)
234 resolutionFactor = 1;
235
236 while (resolution * resolutionFactor > MAX_RESOLUTION)
237 {
238 if (resolutionFactor < 2) // should not happen with provided options
239 {
240 int newResolution = resolution;
241 while (newResolution > 1 && newResolution * resolutionFactor > MAX_RESOLUTION)
242 {
243 newResolution /= 2;
244 }
245
247 "Resolution %1 is greater than max allowed %2 resolution; using %3",
248 resolution,
249 MAX_RESOLUTION,
250 newResolution,
251 level: LogLevel.WARNING);
252
253 resolution = newResolution;
254 }
255 else
256 {
257 int newResolutionFactor = resolutionFactor;
258 while (newResolutionFactor > 1 && resolution * newResolutionFactor > MAX_RESOLUTION)
259 {
260 newResolutionFactor *= 0.5;
261 }
262
264 "Resolution %1 multiplied by %2 (%3) is greater than max allowed %4 resolution; changing multiplier to %5",
265 resolution,
266 resolutionFactor,
267 resolution * resolutionFactor,
268 MAX_RESOLUTION,
269 newResolutionFactor,
270 level: LogLevel.WARNING);
271
272 resolutionFactor = newResolutionFactor;
273 }
274 }
275
276 if (resolutionFactor > 1)
277 {
278 Debug.BeginTimeMeasure();
279 if (SCR_ImageHelper.IncreaseResolution(imageData, resolution, resolution, resolutionFactor))
280 {
281 Debug.EndTimeMeasure(string.Format("Increasing image side by a factor of %1 (from %2×%2 to %3×%3) - SUCCESS", resolutionFactor, resolution, resolution * resolutionFactor));
282 resolution *= resolutionFactor;
283 }
284 else
285 {
286 Debug.EndTimeMeasure(string.Format("Increasing image side by a factor of %1 (from %2×%2 to %3×%3) - FAILURE", resolutionFactor, resolution, resolution * resolutionFactor));
287 }
288 }
289
290 Debug.BeginTimeMeasure();
291 bool result = SCR_ImageHelper.TEMP_SaveImageDataWrapper(imagePath, resolution, resolution, imageData);
292 Debug.EndTimeMeasure("Writing image " + imagePath);
293
294 return result;
295 }
296
297 //------------------------------------------------------------------------------------------------
300 static string GetResolutionFactorEnum(array<int> multipliers = null)
301 {
302 array<int> multipliersRef = multipliers;
303 int multipliersCount;
304 if (multipliersRef)
305 multipliersCount = multipliersRef.Count();
306
307 if (multipliersCount < 1)
308 {
309 multipliersRef = { 1, 2, 4, 8 };
310 multipliersCount = 4;
311 }
312
313 if (multipliersCount > 0)
314 {
315 multipliersRef.Sort();
316 for (int i = multipliersCount - 1; i >= 0; --i)
317 {
318 int multiplier = multipliersRef[i];
319 if (multiplier < 1 || multipliersRef.Find(multiplier) != i)
320 {
321 multipliersRef.Remove(i);
322 --multipliersCount;
323 }
324 }
325 }
326
327 if (multipliersCount > 1)
328 multipliersRef.Sort();
329
330 string result;
331 foreach (int i, int multiplier : multipliersRef)
332 {
333 if (i > 0)
334 result += string.Format(";%1,×%1,e.g 64×64 becomes %2×%2", multiplier, 64 * multiplier);
335 else
336 if (multiplier == 1)
337 result += "1,1:1 resolution,1 data point = 1 pixel";
338 else
339 result += string.Format("%1,×%1,e.g 64×64 becomes %2×%2", multiplier, 64 * multiplier);
340 }
341
342 return result;
343 }
344}
SCR_DestructionSynchronizationComponentClass ScriptComponentClass int index
Definition Debug.c:13
Definition Math.c:13
static string GetResolutionFactorEnum(array< int > multipliers=null)
static const int MIN_GRADIENT_RGB
static bool CreateHeatmapImageFromData(string imagePath, notnull array< int > imageData, int colourMode=COLOUR_MODE_GREYSCALE, bool invertColour=false, int maxValueMode=MAX_MODE_RAW, bool highlightValuesAboveMax=false, int resolutionFactor=1)
Definition float.c:13
Definition int.c:13
LogLevel
Enum with severity of the logging message.
Definition LogLevel.c:14
proto void PrintFormat(string fmt, void param1=NULL, void param2=NULL, void param3=NULL, void param4=NULL, void param5=NULL, void param6=NULL, void param7=NULL, void param8=NULL, void param9=NULL, LogLevel level=LogLevel.NORMAL)