Neuron®
The Neuron® is the basis for the creation of open and secure federated networks for smart societies.
Loading...
Searching...
No Matches
FlameState.cs
1using System;
2using SkiaSharp;
5
7{
8 internal enum ColorMode
9 {
10 Rgba,
11 Hsl
12 }
13
14 internal class FlameState
15 {
16 internal ScriptNode node;
17 internal int[] frequency;
18 internal double[] reds;
19 internal double[] greens;
20 internal double[] blues;
21 internal double x;
22 internal double y;
23 internal double red;
24 internal double green;
25 internal double blue;
26 internal double xMin;
27 internal double xMax;
28 internal double yMin;
29 internal double yMax;
30 internal double sx;
31 internal double sy;
32 internal long N;
33 internal long N0;
34 internal long NrCalculated = 0;
35 internal ColorMode ColorMode;
36 internal int superSampling;
37 internal int width;
38 internal int height;
39 internal int size;
40
41 internal FlameState(Random Gen, double xMin, double xMax, double yMin, double yMax,
42 int Width, int Height, int SuperSampling, long N, ColorMode ColorMode, ScriptNode Node)
43 {
44 this.node = Node;
45 this.x = Gen.NextDouble();
46 this.y = Gen.NextDouble();
47 this.red = 0;
48 this.green = 0;
49 this.blue = 0;
50 this.ColorMode = ColorMode;
51
52 this.N = N;
53 this.N0 = N;
54 this.xMin = xMin;
55 this.xMax = xMax;
56 this.yMin = yMin;
57 this.yMax = yMax;
58 this.superSampling = SuperSampling;
59 this.width = Width * SuperSampling;
60 this.height = Height * SuperSampling;
61
62 this.size = this.width * this.height;
63 this.sx = this.width / (xMax - xMin);
64 this.sy = this.height / (yMax - yMin);
65
66 this.frequency = new int[this.size];
67 this.reds = new double[this.size];
68 this.greens = new double[this.size];
69 this.blues = new double[this.size];
70 }
71
72 internal bool IncHistogram()
73 {
74 if (this.x < this.xMin || this.x > this.xMax || this.y < this.yMin || this.y > this.yMax)
75 return --N > 0;
76
77 int xi = (int)((this.x - this.xMin) * this.sx + 0.5);
78 int yi = this.height - 1 - (int)((this.y - this.yMin) * this.sy + 0.5);
79
80 if (xi < 0 || xi >= this.width || yi < 0 || yi >= this.height)
81 return --N > 0;
82
83 yi *= this.width;
84 yi += xi;
85
86 xi = this.frequency[yi];
87 if (xi < int.MaxValue)
88 this.frequency[yi] = xi + 1;
89
90 switch (this.ColorMode)
91 {
92 case ColorMode.Rgba:
93 this.reds[yi] = (this.reds[yi] + this.red) * 0.5;
94 this.greens[yi] = (this.greens[yi] + this.green) * 0.5;
95 this.blues[yi] = (this.blues[yi] + this.blue) * 0.5;
96 break;
97
98 case ColorMode.Hsl:
99 double d;
100 double Hue = this.reds[yi];
101
102 if (this.red < Hue) // H
103 {
104 d = Hue - this.red;
105 if (d < 0.5)
106 Hue -= d * 0.5;
107 else
108 {
109 d = 1 - d;
110 Hue += d * 0.5;
111 if (Hue >= 1)
112 Hue -= 1;
113 }
114 }
115 else
116 {
117 d = this.red - Hue;
118 if (d < 0.5)
119 Hue += d * 0.5;
120 else
121 {
122 d = 1 - d;
123 Hue -= d * 0.5;
124 if (Hue < 0)
125 Hue += 1;
126 }
127 }
128
129 this.reds[yi] = Hue;
130 this.greens[yi] = (this.greens[yi] + this.green) * 0.5; // S
131 this.blues[yi] = (this.blues[yi] + this.blue) * 0.5; // L
132 break;
133 }
134 return --N > 0;
135 }
136
137 internal void Add(FlameState State)
138 {
139 int f1, f2;
140 long f;
141 int i;
142
143 for (i = 0; i < this.size; i++)
144 {
145 f2 = State.frequency[i];
146 if (f2 == 0)
147 continue;
148
149 f1 = this.frequency[i];
150
151 if (f1 == 0)
152 {
153 this.frequency[i] = f2;
154 this.reds[i] = State.reds[i];
155 this.greens[i] = State.greens[i];
156 this.blues[i] = State.blues[i];
157 }
158 else
159 {
160 f = f1;
161 f += f2;
162
163 if (f > int.MaxValue)
164 this.frequency[i] = int.MaxValue;
165 else
166 this.frequency[i] = (int)f;
167
168 this.reds[i] = (f1 * this.reds[i] + f2 * State.reds[i]) / f;
169 this.greens[i] = (f1 * this.greens[i] + f2 * State.greens[i]) / f;
170 this.blues[i] = (f1 * this.blues[i] + f2 * State.blues[i]) / f;
171 }
172 }
173 }
174
175 internal PixelInformation RenderBitmapRgba(double Gamma, double Vibrancy, bool Preview, SKColor? Background)
176 {
177 int[] Frequency;
178 double[] Reds;
179 double[] Greens;
180 double[] Blues;
181
182 if (Preview)
183 {
184 Frequency = (int[])this.frequency.Clone();
185 Reds = (double[])this.reds.Clone();
186 Greens = (double[])this.greens.Clone();
187 Blues = (double[])this.blues.Clone();
188 }
189 else
190 {
191 Frequency = this.frequency;
192 Reds = this.reds;
193 Greens = this.greens;
194 Blues = this.blues;
195 }
196
197 int Width = this.width / this.superSampling;
198 int Height = this.height / this.superSampling;
199 int size = Width * Height * 4;
200 byte[] rgb = new byte[size];
201 int x, y;
202 int dst = 0;
203 int srcY;
204 int src;
205 int si, a;
206 int rowStep = Width * this.superSampling;
207 int rowStep2 = rowStep - this.superSampling;
208 int srcYStep = rowStep * this.superSampling;
209 int dx, dy;
210 int i, j;
211 double r, g, b, s, s2;
212 int freq, maxfreq = 0;
213 double GammaComponent = Gamma * (1 - Vibrancy) + Vibrancy;
214 double GammaAlpha = Gamma * Vibrancy + (1 - Vibrancy);
215 bool HasBg = Background.HasValue;
216 byte BgR, BgG, BgB;
217
218 if (HasBg)
219 {
220 BgR = Background.Value.Red;
221 BgG = Background.Value.Green;
222 BgB = Background.Value.Blue;
223 }
224 else
225 BgR = BgG = BgB = 0;
226
227 s2 = Math.Pow(255.0, GammaComponent);
228
229 if (this.superSampling > 1)
230 {
231 for (y = srcY = 0; y < Height; y++, srcY += srcYStep)
232 {
233 for (x = 0, src = srcY; x < Width; x++, src += this.superSampling)
234 {
235 si = src;
236 r = g = b = 0.0;
237 freq = 0;
238
239 for (dy = 0; dy < this.superSampling; dy++)
240 {
241 for (dx = 0; dx < this.superSampling; dx++, si++)
242 {
243 j = Frequency[si];
244 if (j > 0)
245 {
246 freq += j;
247 r += j * Reds[si];
248 g += j * Greens[si];
249 b += j * Blues[si];
250 }
251 }
252
253 si += rowStep2;
254 }
255
256 if (freq == 0)
257 Frequency[src] = 0;
258 else
259 {
260 if (freq > maxfreq)
261 maxfreq = freq;
262
263 s = s2 / freq;
264 Frequency[src] = freq;
265 Reds[src] = r * s;
266 Greens[src] = g * s;
267 Blues[src] = b * s;
268 }
269 }
270 }
271 }
272 else
273 {
274 maxfreq = 0;
275 foreach (int F in Frequency)
276 {
277 if (F > maxfreq)
278 maxfreq = F;
279 }
280 }
281
282 if (maxfreq == 0)
283 s = 1;
284 else
285 s = Math.Pow(255.0, GammaAlpha) / Math.Log(maxfreq);
286
287 GammaComponent = 1.0 / GammaComponent;
288 GammaAlpha = 1.0 / GammaAlpha;
289
290 if (Vibrancy == 1) // Only gamma correction on the alpha-channel
291 {
292 for (y = srcY = 0; y < Height; y++, srcY += srcYStep)
293 {
294 for (x = 0, src = srcY; x < Width; x++, src += this.superSampling)
295 {
296 i = Frequency[src];
297
298 if (i == 0)
299 {
300 if (HasBg)
301 {
302 rgb[dst++] = BgB;
303 rgb[dst++] = BgG;
304 rgb[dst++] = BgR;
305 rgb[dst++] = 0xff;
306 }
307 else
308 {
309 rgb[dst++] = 0;
310 rgb[dst++] = 0;
311 rgb[dst++] = 0;
312 rgb[dst++] = 0;
313 }
314 }
315 else
316 {
317 if (HasBg)
318 {
319 a = (int)(Math.Pow(Math.Log(i) * s, GammaAlpha));
320
321 si = (int)Blues[src];
322 si = (si * a + BgB * (255 - a) + 128) / 255;
323 if (si < 0)
324 rgb[dst++] = 0;
325 else if (si > 255)
326 rgb[dst++] = 255;
327 else
328 rgb[dst++] = (byte)si;
329
330 si = (int)Greens[src];
331 si = (si * a + BgG * (255 - a) + 128) / 255;
332 if (si < 0)
333 rgb[dst++] = 0;
334 else if (si > 255)
335 rgb[dst++] = 255;
336 else
337 rgb[dst++] = (byte)si;
338
339 si = (int)Reds[src];
340 si = (si * a + BgR * (255 - a) + 128) / 255;
341 if (si < 0)
342 rgb[dst++] = 0;
343 else if (si > 255)
344 rgb[dst++] = 255;
345 else
346 rgb[dst++] = (byte)si;
347
348 rgb[dst++] = 255;
349 }
350 else
351 {
352 si = (int)Blues[src];
353 if (si < 0)
354 rgb[dst++] = 0;
355 else if (si > 255)
356 rgb[dst++] = 255;
357 else
358 rgb[dst++] = (byte)si;
359
360 si = (int)Greens[src];
361 if (si < 0)
362 rgb[dst++] = 0;
363 else if (si > 255)
364 rgb[dst++] = 255;
365 else
366 rgb[dst++] = (byte)si;
367
368 si = (int)Reds[src];
369 if (si < 0)
370 rgb[dst++] = 0;
371 else if (si > 255)
372 rgb[dst++] = 255;
373 else
374 rgb[dst++] = (byte)si;
375
376 a = (int)(Math.Pow(Math.Log(i) * s, GammaAlpha));
377 if (a < 0)
378 rgb[dst++] = 0;
379 else if (a > 255)
380 rgb[dst++] = 255;
381 else
382 rgb[dst++] = (byte)a;
383 }
384 }
385 }
386 }
387 }
388 else if (Vibrancy == 0) // Only gamma correction on the individual components.
389 {
390 for (y = srcY = 0; y < Height; y++, srcY += srcYStep)
391 {
392 for (x = 0, src = srcY; x < Width; x++, src += this.superSampling)
393 {
394 i = Frequency[src];
395
396 if (i == 0)
397 {
398 if (HasBg)
399 {
400 rgb[dst++] = BgB;
401 rgb[dst++] = BgG;
402 rgb[dst++] = BgR;
403 rgb[dst++] = 0xff;
404 }
405 else
406 {
407 rgb[dst++] = 0;
408 rgb[dst++] = 0;
409 rgb[dst++] = 0;
410 rgb[dst++] = 0;
411 }
412 }
413 else
414 {
415 if (HasBg)
416 {
417 a = (int)(Math.Log(i) * s);
418
419 si = (int)Math.Pow(Blues[src], GammaComponent);
420 si = (si * a + BgB * (255 - a) + 128) / 255;
421 if (si < 0)
422 rgb[dst++] = 0;
423 else if (si > 255)
424 rgb[dst++] = 255;
425 else
426 rgb[dst++] = (byte)si;
427
428 si = (int)Math.Pow(Greens[src], GammaComponent);
429 si = (si * a + BgG * (255 - a) + 128) / 255;
430 if (si < 0)
431 rgb[dst++] = 0;
432 else if (si > 255)
433 rgb[dst++] = 255;
434 else
435 rgb[dst++] = (byte)si;
436
437 si = (int)Math.Pow(Reds[src], GammaComponent);
438 si = (si * a + BgR * (255 - a) + 128) / 255;
439 if (si < 0)
440 rgb[dst++] = 0;
441 else if (si > 255)
442 rgb[dst++] = 255;
443 else
444 rgb[dst++] = (byte)si;
445
446 rgb[dst++] = 255;
447 }
448 else
449 {
450 si = (int)Math.Pow(Blues[src], GammaComponent);
451 if (si < 0)
452 rgb[dst++] = 0;
453 else if (si > 255)
454 rgb[dst++] = 255;
455 else
456 rgb[dst++] = (byte)si;
457
458 si = (int)Math.Pow(Greens[src], GammaComponent);
459 if (si < 0)
460 rgb[dst++] = 0;
461 else if (si > 255)
462 rgb[dst++] = 255;
463 else
464 rgb[dst++] = (byte)si;
465
466 si = (int)Math.Pow(Reds[src], GammaComponent);
467 if (si < 0)
468 rgb[dst++] = 0;
469 else if (si > 255)
470 rgb[dst++] = 255;
471 else
472 rgb[dst++] = (byte)si;
473
474 a = (int)(Math.Log(i) * s);
475 if (a < 0)
476 rgb[dst++] = 0;
477 else if (a > 255)
478 rgb[dst++] = 255;
479 else
480 rgb[dst++] = (byte)a;
481 }
482 }
483 }
484 }
485 }
486 else // Interpolated gamma correction on both the components and the alpha channel.
487 {
488 for (y = srcY = 0; y < Height; y++, srcY += srcYStep)
489 {
490 for (x = 0, src = srcY; x < Width; x++, src += this.superSampling)
491 {
492 i = Frequency[src];
493
494 if (i == 0)
495 {
496 if (HasBg)
497 {
498 rgb[dst++] = BgB;
499 rgb[dst++] = BgG;
500 rgb[dst++] = BgR;
501 rgb[dst++] = 0xff;
502 }
503 else
504 {
505 rgb[dst++] = 0;
506 rgb[dst++] = 0;
507 rgb[dst++] = 0;
508 rgb[dst++] = 0;
509 }
510 }
511 else
512 {
513 if (HasBg)
514 {
515 a = (int)(Math.Pow(Math.Log(i) * s, GammaAlpha));
516
517 si = (int)Math.Pow(Blues[src], GammaComponent);
518 si = (si * a + BgB * (255 - a) + 128) / 255;
519 if (si < 0)
520 rgb[dst++] = 0;
521 else if (si > 255)
522 rgb[dst++] = 255;
523 else
524 rgb[dst++] = (byte)si;
525
526 si = (int)Math.Pow(Greens[src], GammaComponent);
527 si = (si * a + BgG * (255 - a) + 128) / 255;
528 if (si < 0)
529 rgb[dst++] = 0;
530 else if (si > 255)
531 rgb[dst++] = 255;
532 else
533 rgb[dst++] = (byte)si;
534
535 si = (int)Math.Pow(Reds[src], GammaComponent);
536 si = (si * a + BgR * (255 - a) + 128) / 255;
537 if (si < 0)
538 rgb[dst++] = 0;
539 else if (si > 255)
540 rgb[dst++] = 255;
541 else
542 rgb[dst++] = (byte)si;
543
544 rgb[dst++] = 255;
545 }
546 else
547 {
548 si = (int)Math.Pow(Blues[src], GammaComponent);
549 if (si < 0)
550 rgb[dst++] = 0;
551 else if (si > 255)
552 rgb[dst++] = 255;
553 else
554 rgb[dst++] = (byte)si;
555
556 si = (int)Math.Pow(Greens[src], GammaComponent);
557 if (si < 0)
558 rgb[dst++] = 0;
559 else if (si > 255)
560 rgb[dst++] = 255;
561 else
562 rgb[dst++] = (byte)si;
563
564 si = (int)Math.Pow(Reds[src], GammaComponent);
565 if (si < 0)
566 rgb[dst++] = 0;
567 else if (si > 255)
568 rgb[dst++] = 255;
569 else
570 rgb[dst++] = (byte)si;
571
572 a = (int)(Math.Pow(Math.Log(i) * s, GammaAlpha));
573 if (a < 0)
574 rgb[dst++] = 0;
575 else if (a > 255)
576 rgb[dst++] = 255;
577 else
578 rgb[dst++] = (byte)a;
579 }
580 }
581 }
582 }
583 }
584
585 return new PixelInformationRaw(SKColorType.Bgra8888, rgb, Width, Height, Width << 2);
586 }
587
588 internal PixelInformation RenderBitmapHsl(double Gamma, double LightFactor, bool Preview, SKColor? Background)
589 {
590 int[] Frequency;
591 double[] Hues;
592 double[] Saturations;
593 double[] Lights;
594
595 if (Preview)
596 {
597 Frequency = (int[])this.frequency.Clone();
598 Hues = (double[])this.reds.Clone();
599 Saturations = (double[])this.greens.Clone();
600 Lights = (double[])this.blues.Clone();
601 }
602 else
603 {
604 Frequency = this.frequency;
605 Hues = this.reds;
606 Saturations = this.greens;
607 Lights = this.blues;
608 }
609
610 int Width = this.width / this.superSampling;
611 int Height = this.height / this.superSampling;
612 int size = Width * Height * 4;
613 byte[] rgb = new byte[size];
614 int x, y;
615 int dst = 0;
616 int srcY;
617 int src;
618 int si;
619 int rowStep = Width * this.superSampling;
620 int rowStep2 = rowStep - this.superSampling;
621 int srcYStep = rowStep * this.superSampling;
622 int dx, dy;
623 int i, j;
624 double H, S, L;
625 int freq, maxfreq;
626 long R2, G2, B2;
627 SKColor cl;
628 bool HasBg = Background.HasValue;
629 byte BgR, BgG, BgB;
630
631 if (HasBg)
632 {
633 BgR = Background.Value.Red;
634 BgG = Background.Value.Green;
635 BgB = Background.Value.Blue;
636 }
637 else
638 BgR = BgG = BgB = 0;
639
640 maxfreq = 0;
641 foreach (int F in Frequency)
642 {
643 if (F > maxfreq)
644 maxfreq = F;
645 }
646
647 Gamma = 1.0 / Gamma;
648
649 if (this.superSampling == 1)
650 {
651 for (y = srcY = 0; y < Height; y++, srcY += srcYStep)
652 {
653 for (x = 0, src = srcY; x < Width; x++, src++)
654 {
655 i = Frequency[src];
656
657 if (i == 0)
658 {
659 if (HasBg)
660 {
661 rgb[dst++] = BgB;
662 rgb[dst++] = BgG;
663 rgb[dst++] = BgR;
664 }
665 else
666 {
667 rgb[dst++] = 0;
668 rgb[dst++] = 0;
669 rgb[dst++] = 0;
670 }
671
672 rgb[dst++] = 0xff;
673 }
674 else
675 {
676 H = Hues[src] * 360;
677 S = Math.Pow(Saturations[src], Gamma);
678 L = Math.Pow((Lights[src] * i) / maxfreq, Gamma) * LightFactor;
679
680 if (S > 1)
681 S = 1;
682
683 if (L > 1)
684 L = 1;
685
686 cl = Graph.ToColorHSL(H, S, L);
687 rgb[dst++] = cl.Blue;
688 rgb[dst++] = cl.Green;
689 rgb[dst++] = cl.Red;
690 rgb[dst++] = 0xff;
691 }
692 }
693 }
694 }
695 else
696 {
697 for (y = srcY = 0; y < Height; y++, srcY += srcYStep)
698 {
699 for (x = 0, src = srcY; x < Width; x++, src += this.superSampling)
700 {
701 si = src;
702 R2 = G2 = B2 = 0;
703 freq = 0;
704
705 for (dy = 0; dy < this.superSampling; dy++)
706 {
707 for (dx = 0; dx < this.superSampling; dx++, si++)
708 {
709 j = Frequency[si];
710 if (j > 0)
711 {
712 H = Hues[si] * 360;
713 S = Math.Pow(Saturations[si], Gamma);
714 L = Math.Pow((Lights[si] * j) / maxfreq, Gamma) * LightFactor;
715
716 if (S > 1)
717 S = 1;
718
719 if (L > 1)
720 L = 1;
721
722 cl = Graph.ToColorHSL(H, S, L);
723
724 freq += j;
725 R2 += j * cl.Red;
726 G2 += j * cl.Green;
727 B2 += j * cl.Blue;
728 }
729 }
730
731 si += rowStep2;
732 }
733
734 if (freq == 0)
735 {
736 if (HasBg)
737 {
738 rgb[dst++] = BgB;
739 rgb[dst++] = BgG;
740 rgb[dst++] = BgR;
741 }
742 else
743 {
744 rgb[dst++] = 0;
745 rgb[dst++] = 0;
746 rgb[dst++] = 0;
747 }
748
749 rgb[dst++] = 0xff;
750 }
751 else
752 {
753 R2 /= freq;
754 if (R2 > 255)
755 R2 = 255;
756
757 G2 /= freq;
758 if (G2 > 255)
759 G2 = 255;
760
761 B2 /= freq;
762 if (B2 > 255)
763 B2 = 255;
764
765 rgb[dst++] = (byte)B2;
766 rgb[dst++] = (byte)G2;
767 rgb[dst++] = (byte)R2;
768 rgb[dst++] = 0xff;
769 }
770 }
771 }
772 }
773
774 return new PixelInformationRaw(SKColorType.Bgra8888, rgb, Width, Height, Width << 2);
775 }
776
777 }
778}
Base class for graphs.
Definition: Graph.cs:79
static SKColor ToColorHSL(double H, double S, double L)
Creates a Color from its HSL representation.
Definition: Graph.cs:846
Contains pixel information
Contains pixel information in a raw unencoded format.
Base class for all nodes in a parsed script tree.
Definition: ScriptNode.cs:69