void Visualize() { int bWidth, bHeight, iWidth, iHeight, spls, splCount, stride; long bLength, iLength, byteLen = 0, i, j, spl; float currSpl; double palOffs, palScale, min, max, offs, scale; VisPaletteType palType; bool isDone, doRepop, isPalRel; FloatColor liveClr, currClr; double[] result; bool[] isAlive; FloatColor[] palette; byte[] bytes = new byte[0]; BitmapSource src; while (true) { startEvent.WaitOne(); lock (queueLock) { bWidth = this.bWidth; bHeight = this.bHeight; iWidth = this.iWidth; iHeight = this.iHeight; spls = this.spls; splCount = spls * spls; bLength = this.bLength; iLength = iWidth * iHeight; stride = iWidth * bpp; result = this.result; isAlive = this.isAlive; isDone = this.isDone; palette = this.palette; liveClr = this.liveClr; palType = this.paletteType; palOffs = this.offs; palScale = this.scale; doRepop = this.byteLen != byteLen; byteLen = this.byteLen; } if (bWidth == 0 || bHeight == 0) continue; if (doRepop) bytes = new byte[byteLen]; offs = isDone ? palOffs : 0; isPalRel = palType == VisPaletteType.Relative || !isDone; if (isPalRel) { min = double.MaxValue; max = double.MinValue; for (i = 1; i < bLength; i++) { if (!isAlive[i]) { min = Math.Min(min, result[i]); max = Math.Max(max, result[i]); } } Console.WriteLine($"[Visualizer] Current minimum: {min}; current maximum: {max}."); offs -= min; scale = (isDone ? palScale * (palette.Length - 1) : 1) / (max - min); } else scale = (palType == VisPaletteType.CyclicSingle ? 1 : palette.Length) / palScale; if (isDone) { for (int row = 0; row < iHeight; row++) { for (int col = 0; col < iWidth; col++) { i = (col + row * bWidth) * spls; j = (col + row * iWidth) * bpp; currClr = new FloatColor(0, 0, 0, 0); for (int sRow = 0; sRow < spls; sRow++) { for (int sCol = 0; sCol < spls; sCol++) { spl = i + sCol + sRow * bWidth; currClr += isAlive[spl] ? liveClr : isPalRel ? GetColor(palette, liveClr, (result[spl] + offs) * scale) : GetColor(palette, liveClr, Math.Log(result[spl] + 1) * scale); } } currClr /= splCount; bytes[j] = (byte)(currClr.B * 255); bytes[j + 1] = (byte)(currClr.G * 255); bytes[j + 2] = (byte)(currClr.R * 255); bytes[j + 3] = (byte)(currClr.A * 255); } } } else { for (int row = 0; row < iHeight; row++) { for (int col = 0; col < iWidth; col++) { i = (col + row * bWidth) * spls; j = (col + row * iWidth) * bpp; currSpl = 0; for (int sRow = 0; sRow < spls; sRow++) { for (int sCol = 0; sCol < spls; sCol++) { spl = i + sCol + sRow * bWidth; currSpl += isAlive[spl] ? 0 : (float)((result[spl] + offs) * scale); } } currSpl /= splCount; bytes[j] = bytes[j + 1] = bytes[j + 2] = (byte)(Math.Max(0, Math.Min(1, currSpl)) * 255); bytes[j + 3] = (byte)255; } } } src = BitmapSource.Create(iWidth, iHeight, dpiX, dpiY, PixelFormats.Bgra32, null, bytes, stride); Source = src.GetAsFrozen() as BitmapSource; visualized?.Invoke(this); } }