MyCaffe  1.12.2.41
Deep learning software for Windows C# programmers.
ColorMapper.cs
1using System;
2using System.Collections.Generic;
3using System.Drawing;
4using System.Linq;
5using System.Text;
6using System.Threading.Tasks;
7
8namespace MyCaffe.basecode
9{
13 public class ColorMapper
14 {
15 double m_dfMin = 0;
16 double m_dfMax = 0;
17 double m_dfMid = 0;
18 int m_nMidIdx = 0;
19 List<Tuple<double, int>> m_rgQuads0 = new List<Tuple<double, int>>();
20 List<Tuple<double, int>> m_rgQuads1 = new List<Tuple<double, int>>();
21 int m_nResolution;
22 List<KeyValuePair<Color, SizeF>> m_rgColorMappings = new List<KeyValuePair<Color, SizeF>>();
23 int m_nLastIdx = -1;
24 List<List<double>> m_rgrgColors = new List<List<double>>();
25 Color m_clrDefault;
26 Color m_clrError;
27 Color m_clrNoMinMax = Color.HotPink;
28
29
33 public enum COLORSCHEME
34 {
38 NORMAL,
42 GBR
43 }
44
54 public ColorMapper(double dfMin, double dfMax, Color clrDefault, Color clrError, COLORSCHEME clrScheme = COLORSCHEME.NORMAL, int nResolution = 160)
55 {
56 m_clrDefault = clrDefault;
57 m_clrError = clrError;
58 m_nResolution = nResolution;
59 m_dfMin = dfMin;
60 m_dfMax = dfMax;
61
62 if (clrScheme == COLORSCHEME.GBR)
63 {
64 m_rgrgColors.Add(new List<double>() { 1, 0, 0 }); // red
65 m_rgrgColors.Add(new List<double>() { 0, 0, 0.5 }); // blue
66 m_rgrgColors.Add(new List<double>() { 0, 1, 0 }); // green
67 }
68 else
69 {
70 m_rgrgColors.Add(new List<double>() { 0, 0, 0 }); // black
71 m_rgrgColors.Add(new List<double>() { 0, 0, 1 }); // blue
72 m_rgrgColors.Add(new List<double>() { 0, 1, 0 }); // green
73 m_rgrgColors.Add(new List<double>() { 1, 0, 0 }); // red
74 m_rgrgColors.Add(new List<double>() { 1, 1, 0 }); // yellow
75 }
76
77
78 double dfMin1 = dfMin;
79 double dfMax1 = dfMax;
80
81 double dfRange = dfMax - dfMin;
82 double dfInc = dfRange / m_nResolution;
83
84 dfMax = dfMin + dfInc;
85
86 while (dfMax < m_dfMax)
87 {
88 Color clr = calculate(dfMin);
89 m_rgColorMappings.Add(new KeyValuePair<Color, SizeF>(clr, new SizeF((float)dfMin, (float)dfMax)));
90 dfMin = dfMax;
91 dfMax += dfInc;
92 }
93
94 if (m_rgColorMappings.Count == 0)
95 m_rgColorMappings.Add(new KeyValuePair<Color, SizeF>(Color.Black, new SizeF((float)dfMin1, (float)dfMax1)));
96
97 m_dfMid = dfRange / 2;
98 m_nMidIdx = m_rgColorMappings.Count / 2;
99 m_rgQuads0 = createSearchQuads(0, 0, m_rgColorMappings.Count, dfRange);
100 m_rgQuads1 = createSearchQuads(m_dfMid, m_nMidIdx, m_rgColorMappings.Count, dfRange);
101 }
102
113 public ColorMapper(double dfMin, double dfMax, Color clrDefault, Color clrError, List<double> rgClrStart, List<double> rgClrEnd, int nResolution = 160)
114 {
115 m_clrDefault = clrDefault;
116 m_clrError = clrError;
117 m_nResolution = nResolution;
118 m_dfMin = dfMin;
119 m_dfMax = dfMax;
120
121 m_rgrgColors.Add(rgClrStart);
122 m_rgrgColors.Add(rgClrEnd);
123
124 double dfRange = dfMax - dfMin;
125 double dfInc = dfRange / m_nResolution;
126
127 dfMax = dfMin + dfInc;
128
129 while (dfMax < m_dfMax)
130 {
131 Color clr = calculate(dfMin);
132 m_rgColorMappings.Add(new KeyValuePair<Color, SizeF>(clr, new SizeF((float)dfMin, (float)dfMax)));
133 dfMin = dfMax;
134 dfMax += dfInc;
135 }
136
137 m_dfMid = dfRange / 2;
138 m_nMidIdx = m_rgColorMappings.Count / 2;
139 m_rgQuads0 = createSearchQuads(0, 0, m_rgColorMappings.Count, dfRange);
140 m_rgQuads1 = createSearchQuads(m_dfMid, m_nMidIdx, m_rgColorMappings.Count, dfRange);
141 }
142
143 private List<Tuple<double, int>> createSearchQuads(double dfStart, int nIdxStart, int nItemCount, double dfRange)
144 {
145 List<Tuple<double, int>> rgQuads = new List<Tuple<double, int>>();
146 int nCount = (nItemCount < 160) ? 2 : 4;
147 double dfStep = 0.5 / nCount;
148 double dfPortion = dfStep;
149
150 for (int i = 1; i < nCount; i++)
151 {
152 double dfQuad = dfStart + dfRange * dfPortion;
153 int nIdx = nIdxStart + (int)(nItemCount * dfPortion);
154 rgQuads.Add(new Tuple<double, int>(dfQuad, nIdx));
155
156 dfPortion += dfStep;
157 }
158
159 return rgQuads;
160 }
161
165 public int Resolution
166 {
167 get { return m_nResolution; }
168 }
169
173 public Color NoMinMaxColor
174 {
175 get { return m_clrNoMinMax; }
176 set { m_clrNoMinMax = value; }
177 }
178
184 public Color GetColorLegacy(double dfVal)
185 {
186 if (double.IsNaN(dfVal) || double.IsInfinity(dfVal))
187 return m_clrError;
188
189 if (dfVal >= m_dfMin || dfVal <= m_dfMax)
190 {
191 if (m_rgColorMappings.Count > 0)
192 {
193 int nStart = 0;
194 int nEnd = m_rgColorMappings.Count;
195 List<Tuple<double, int>> rgQuads;
196
197 if (dfVal < m_dfMid)
198 {
199 nEnd = m_nMidIdx + 1;
200 rgQuads = m_rgQuads0;
201 }
202 else
203 {
204 nStart = m_nMidIdx - 1;
205 rgQuads = m_rgQuads1;
206 }
207
208 for (int i = 0; i < rgQuads.Count; i++)
209 {
210 if (dfVal < rgQuads[i].Item1)
211 {
212 if (i > 0)
213 nStart = rgQuads[i].Item2 - 1;
214
215 if (i < rgQuads.Count - 1)
216 nEnd = rgQuads[i].Item2 + 1;
217
218 break;
219 }
220 }
221
222 if (nStart < 0)
223 nStart = 0;
224
225 if (nEnd > m_rgColorMappings.Count)
226 nEnd = m_rgColorMappings.Count;
227
228 for (int i = nStart; i < nEnd; i++)
229 {
230 if (dfVal < m_rgColorMappings[i].Value.Height && dfVal >= m_rgColorMappings[i].Value.Width)
231 return m_rgColorMappings[i].Key;
232 }
233
234 if (dfVal == m_rgColorMappings[m_rgColorMappings.Count - 1].Value.Height)
235 return m_rgColorMappings[m_rgColorMappings.Count - 1].Key;
236 }
237 else if (m_dfMin == m_dfMax && m_dfMin == 0)
238 {
239 return m_clrNoMinMax;
240 }
241 }
242
243 return m_clrDefault;
244 }
245
251 public double GetValue(Color clr)
252 {
253 List<KeyValuePair<Color, SizeF>> rgItems = m_rgColorMappings.ToList();
254 Color clr0 = Color.Black;
255
256 for (int i = 0; i < rgItems.Count; i++)
257 {
258 Color clr1 = rgItems[i].Key;
259 double dfMin = rgItems[i].Value.Width;
260 double dfMax = rgItems[i].Value.Height;
261
262 if (i == 0)
263 {
264 if (clr.R <= clr1.R && clr.G <= clr1.G && clr.B <= clr1.B)
265 return dfMin + (dfMax - dfMin) / 2;
266 }
267 else
268 {
269 if (((clr1.R >= clr0.R && clr.R <= clr1.R) ||
270 (clr1.R < clr0.R && clr.R >= clr1.R)) &&
271 ((clr1.G >= clr0.G && clr.G <= clr1.G) ||
272 (clr1.G < clr0.G && clr.G >= clr1.G)) &&
273 ((clr1.B >= clr0.B && clr.B <= clr1.B) ||
274 (clr1.B < clr0.B && clr.B >= clr1.B)))
275 return dfMin + (dfMax - dfMin) / 2;
276 }
277
278 clr0 = clr1;
279 }
280
281 int nCount = rgItems.Count;
282 double dfMin1 = rgItems[nCount - 1].Value.Width;
283 double dfMax1 = rgItems[nCount - 1].Value.Height;
284
285 return dfMin1 + (dfMax1 - dfMin1) / 2;
286 }
287
297 private Color calculate(double dfVal)
298 {
299 double dfMin = m_dfMin;
300 double dfMax = m_dfMax;
301 double dfRange = dfMax - dfMin;
302
303 // Convert into [0,1] range.
304 dfVal = (dfVal - dfMin) / dfRange;
305
306 int nIdx1 = 0; // |-- desired color will fall between these two indexes.
307 int nIdx2 = 0; // |
308 double dfFraction = 0; // Fraction between two indexes where the value is located.
309
310 if (dfVal < -1)
311 {
312 nIdx1 = 0;
313 nIdx2 = 0;
314 }
315 else if (dfVal > 1)
316 {
317 nIdx1 = m_rgrgColors.Count - 1;
318 nIdx2 = m_rgrgColors.Count - 1;
319 }
320 else
321 {
322 dfVal *= (m_rgrgColors.Count - 1);
323 nIdx1 = (int)Math.Floor(dfVal); // desired color will be after this index.
324 nIdx2 = nIdx1 + 1; // .. and this index (inclusive).
325 dfFraction = dfVal - (double)nIdx1; // distance between two indexes (0-1).
326 }
327
328 if (nIdx1 < 0 || nIdx2 < 0)
329 return m_clrError;
330
331 double dfR = (m_rgrgColors[nIdx2][0] - m_rgrgColors[nIdx1][0]) * dfFraction + m_rgrgColors[nIdx1][0];
332 double dfG = (m_rgrgColors[nIdx2][1] - m_rgrgColors[nIdx1][1]) * dfFraction + m_rgrgColors[nIdx1][1];
333 double dfB = (m_rgrgColors[nIdx2][2] - m_rgrgColors[nIdx1][2]) * dfFraction + m_rgrgColors[nIdx1][2];
334
335 int nR = (int)(dfR * 255);
336 int nG = (int)(dfG * 255);
337 int nB = (int)(dfB * 255);
338
339 return Color.FromArgb(nR, nG, nB);
340 }
341
350 public Color GetColor(double dfVal)
351 {
352 KeyValuePair<Color, SizeF> item;
353
354 if (double.IsNaN(dfVal) || double.IsInfinity(dfVal))
355 return m_clrError;
356
357 else if (m_dfMin == m_dfMax && m_dfMin == 0)
358 return m_clrNoMinMax;
359
360 else
361 {
362 if (m_nLastIdx >= 0 && m_nLastIdx < m_rgColorMappings.Count)
363 {
364 item = m_rgColorMappings[m_nLastIdx];
365 if (dfVal < item.Value.Height && dfVal >= item.Value.Width)
366 return item.Key;
367 }
368
369 item = m_rgColorMappings[m_rgColorMappings.Count - 1];
370 if (dfVal >= item.Value.Width)
371 return item.Key;
372
373 item = m_rgColorMappings[0];
374 if (dfVal < item.Value.Height)
375 return item.Key;
376 }
377
378 int nMinNum = 0;
379 int nMaxNum = m_rgColorMappings.Count - 1;
380
381 while (nMinNum <= nMaxNum)
382 {
383 int nMid = (nMinNum + nMaxNum) / 2;
384 item = m_rgColorMappings[nMid];
385 SizeF sz = item.Value;
386
387 if (dfVal < sz.Height && dfVal >= sz.Width)
388 {
389 m_nLastIdx = nMid;
390 return item.Key;
391 }
392
393 else if (dfVal == sz.Height)
394 {
395 m_nLastIdx = nMid + 1;
396 return m_rgColorMappings[nMid + 1].Key;
397 }
398
399 else if (dfVal < sz.Width)
400 nMaxNum = nMid - 1;
401
402 else if (dfVal >= sz.Height)
403 nMinNum = nMid + 1;
404
405 else
406 break;
407 }
408
409 return m_clrDefault;
410 }
411 }
412}
The ColorMapper maps a value within a number range, to a Color within a color scheme.
Definition: ColorMapper.cs:14
Color NoMinMaxColor
Get/set the color used when the Min and Max both equal 0.
Definition: ColorMapper.cs:174
double GetValue(Color clr)
Returns the value associated with the color.
Definition: ColorMapper.cs:251
Color GetColorLegacy(double dfVal)
Returns the color associated with the value.
Definition: ColorMapper.cs:184
Color GetColor(double dfVal)
Find the color using a binary search algorithm.
Definition: ColorMapper.cs:350
ColorMapper(double dfMin, double dfMax, Color clrDefault, Color clrError, COLORSCHEME clrScheme=COLORSCHEME.NORMAL, int nResolution=160)
The ColorMapper constructor.
Definition: ColorMapper.cs:54
ColorMapper(double dfMin, double dfMax, Color clrDefault, Color clrError, List< double > rgClrStart, List< double > rgClrEnd, int nResolution=160)
The ColorMapper constructor.
Definition: ColorMapper.cs:113
COLORSCHEME
Defines the color scheme to use.
Definition: ColorMapper.cs:34
int Resolution
Returns the color resolution used.
Definition: ColorMapper.cs:166
The MyCaffe.basecode contains all generic types used throughout MyCaffe.
Definition: Annotation.cs:12