Example #1
0
    FloatColor GetColor(FloatColor[] palette, FloatColor fallback, double pos) {
      double wrap = pos % palette.Length;
      if (wrap < 0) wrap = (wrap + palette.Length) % palette.Length;

      if (double.IsNaN(pos)) return fallback;
      else if (double.IsPositiveInfinity(pos)) return palette[palette.Length - 1];
      else if (double.IsNegativeInfinity(pos)) return palette[0];

      if (wrap < 0) wrap += palette.Length;

      int floor = (int)Math.Floor(wrap),
          ceil = (int)Math.Ceiling(pos) % palette.Length;

      if (floor == ceil) return palette[floor];
      else if (ceil - floor > 1) return fallback;

      float t = (float)(wrap - floor);

      FloatColor a = palette[floor],
        b = c1[floor],
        c = c2[floor],
        d = palette[ceil],
        a3 = 3 * a;

      //return (t < 1f / 6 ? a : (t < .5f ? b / 3 : (t < 5f / 6 ? c / 3 : d))).Saturate();

      return (a + t * (b - a3 + t * (a3 - 2 * b + c + t * (b - a - c + d)))).Saturate();
    }
Example #2
0
    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);
      }
    }
Example #3
0
    public void SetPalette(Color[] value, bool isCyclic = true) {
      if (value.Length < 2)
        throw new InvalidOperationException("Palette must have at least two colors.");

      lock (queueLock) {
        palette = (from color in value
                   select (FloatColor)color).ToArray();

        c1 = new FloatColor[palette.Length];
        c2 = new FloatColor[palette.Length];

        if (isCyclic) {
          int im, il;
          FloatColor slope, a3;
          for (int i = 1; i <= c1.Length; i++) {
            im = i % c1.Length; il = i - 1;
            a3 = palette[im] * 3;
            slope = (palette[(i + 1) % palette.Length] - palette[il]) / 2;

            c1[im] = a3 + slope;
            c2[il] = a3 - slope;
          }
        }
        else {
          c1[0] = palette[0] * 2 + palette[1];
          c2[c2.Length - 2] = palette[palette.Length - 2] + palette[palette.Length - 1] * 2;

          c1[c1.Length - 1] = palette[palette.Length - 1] * 2 + palette[0];
          c2[c2.Length - 1] = palette[palette.Length - 1] + palette[0] * 2;

          int il;
          FloatColor slope, a3;
          for (int i = 1; i < palette.Length - 1; i++) {
            il = i - 1;
            a3 = palette[i] * 3;
            slope = (palette[i + 1] - palette[il]) / 2;

            c1[i] = a3 + slope;
            c2[il] = a3 - slope;
          }
        }
      }
    }