Example #1
0
        /// <summary>
        /// Creates a bitmap of the graph.
        /// </summary>
        /// <param name="Settings">Graph settings.</param>
        /// <param name="States">State object(s) that contain graph-specific information about its inner states.
        /// These can be used in calls back to the graph object to make actions on the generated graph.</param>
        /// <returns>Bitmap</returns>
        public override SKImage CreateBitmap(GraphSettings Settings, out object[] States)
        {
            SKImageInfo ImageInfo = new SKImageInfo(this.bitmap.Width, this.bitmap.Height, SKColorType.Bgra8888);
            int         c         = ImageInfo.BytesSize;

            States = new object[0];

            IntPtr Pixels = Marshal.AllocCoTaskMem(c);

            try
            {
                this.bitmap.ReadPixels(ImageInfo, Pixels, ImageInfo.RowBytes, 0, 0);

                using (SKData Data = SKData.Create(Pixels, c))
                {
                    SKImage Result = SKImage.FromPixelData(new SKImageInfo(ImageInfo.Width, ImageInfo.Height, SKColorType.Bgra8888), Data, ImageInfo.RowBytes);
                    Pixels = IntPtr.Zero;

                    return(Result);
                }
            }
            finally
            {
                if (Pixels != IntPtr.Zero)
                {
                    Marshal.FreeCoTaskMem(Pixels);
                }
            }
        }
Example #2
0
 private SKImage GetBitmap(byte[] Pixels)
 {
     using (SKData Data = SKData.CreateCopy(Pixels))
     {
         SKImageInfo ImageInfo = new SKImageInfo(this.width, this.height, SKColorType.Rgba8888, SKAlphaType.Premul);
         return(SKImage.FromPixelData(ImageInfo, Data, this.width << 2));
     }
 }
Example #3
0
        /// <summary>
        /// Encode image to stream.
        /// </summary>
        /// <param name="image">Image to be encoded.</param>
        /// <param name="stream">Stream to which to encode.</param>
        public void Encode(Image image, Stream stream)
        {
            var data = SKData.Create(image.ImageData, image.Size);
            var img  = SKImage.FromPixelData(SKImageInfo.Empty, data, image.Stride);
            var png  = img.Encode(SKEncodedImageFormat.Png, 100);

            png.SaveTo(stream);
        }
Example #4
0
        /// <summary>
        /// Encode image to stream.
        /// </summary>
        /// <param name="image">Image to be encoded.</param>
        /// <param name="stream">Stream to which to encode.</param>
        public void Encode(Image image, Stream stream)
        {
            var data = SKData.Create(image.ImageData, image.Size);
            var img  = SKImage.FromPixelData(SKImageInfo.Empty, data, image.Stride);
            var jpeg = img.Encode(SKEncodedImageFormat.Jpeg, this.QualityLevel);

            jpeg.SaveTo(stream);
        }
Example #5
0
        public static SKImage ToBitmap(int[] ColorIndex, int Width, int Height, SKColor[] Palette)
        {
            int N = Palette.Length;

            byte[]  reds   = new byte[N];
            byte[]  greens = new byte[N];
            byte[]  blues  = new byte[N];
            SKColor cl;
            int     x;

            for (x = 0; x < N; x++)
            {
                cl        = Palette[x];
                reds[x]   = cl.Red;
                greens[x] = cl.Green;
                blues[x]  = cl.Blue;
            }

            int Size  = Width * Height;
            int Size4 = Size * 4;

            byte[] rgb = new byte[Size4];
            int    Index, Index2;
            int    d;

            for (Index = Index2 = 0; Index < Size; Index++)
            {
                d = ColorIndex[Index];

                if (d < 0 || d >= N)
                {
                    rgb[Index2++] = 0;
                    rgb[Index2++] = 0;
                    rgb[Index2++] = 0;
                    rgb[Index2++] = 255;
                }
                else
                {
                    rgb[Index2++] = blues[d];
                    rgb[Index2++] = greens[d];
                    rgb[Index2++] = reds[d];
                    rgb[Index2++] = 255;
                }
            }

            using (SKData Data = SKData.Create(new MemoryStream(rgb)))
            {
                return(SKImage.FromPixelData(new SKImageInfo(Width, Height, SKColorType.Bgra8888), Data, Width * 4));
            }
        }
Example #6
0
        public static SKImage Load(string filePath)
        {
            using var image = Pfim.Pfim.FromFile(filePath);
            var newData = image.Data;
            var stride  = image.Stride;

            var colorType = SkColorType(image, ref newData, ref stride);
            var imageInfo = new SKImageInfo(image.Width, image.Height, colorType);

            using var stream = new SKMemoryStream(newData);
            using var data   = SKData.Create(stream);
            var fromPixelData = SKImage.FromPixelData(imageInfo, data, stride);

            return(fromPixelData);
        }
Example #7
0
        /// <summary>
        /// Converts an image to a SkiaSharp SKImage.
        /// </summary>
        /// <param name="image">Image to convert to SKImage type.</param>
        /// <returns>SKImage.</returns>
        internal static SKImage AsSKImage(this ImageBase image)
        {
            var data      = SKData.Create(image.ImageData, image.Size);
            var colorType = image.PixelFormat switch
            {
                // These are unsupported by SkiaSharp: BGRX_32bpp, BGR_24bpp, Gray_16bpp, RGBA_64bpp
                PixelFormat.BGRA_32bpp => SKColorType.Bgra8888,
                PixelFormat.Gray_8bpp => SKColorType.Gray8,
                PixelFormat.Undefined => SKColorType.Unknown,
                PixelFormat.Gray_16bpp => throw new ArgumentException($"Unsupported pixel format: {image.PixelFormat} (e.g. DepthImage)"),
                      _ => throw new ArgumentException($"Unsupported pixel format: {image.PixelFormat}"),
            };
            var info = new SKImageInfo(image.Width, image.Height, colorType);

            return(SKImage.FromPixelData(info, data, image.Stride));
        }
Example #8
0
        public static FractalGraph CalcNovaMandelbrot(double rCenter, double iCenter, double rDelta, double Rr, double Ri,
                                                      double pr, double pi, SKColor[] Palette, int Width, int Height, ScriptNode Node,
                                                      FractalZoomScript FractalZoomScript, object State)
        {
            byte[]  reds;
            byte[]  greens;
            byte[]  blues;
            double  r0, i0, r1, i1;
            double  dr, di;
            double  r, i;
            double  zr, zi, zr2, zi2, zr3, zi3, zr4, zi4;
            double  aspect;
            double  Temp;
            int     x, y;
            int     n, N;
            int     index;
            SKColor cl;
            double  lnz;
            double  argz;
            double  amp;
            double  phi;

            N      = Palette.Length;
            reds   = new byte[N];
            greens = new byte[N];
            blues  = new byte[N];

            for (x = 0; x < N; x++)
            {
                cl        = Palette[x];
                reds[x]   = cl.Red;
                greens[x] = cl.Green;
                blues[x]  = cl.Blue;
            }

            int    size = Width * Height * 4;
            double Conv = 1e-10;
            double Div  = 1e10;

            byte[] rgb = new byte[size];

            rDelta *= 0.5;
            r0      = rCenter - rDelta;
            r1      = rCenter + rDelta;

            aspect = ((double)Width) / Height;

            i0 = iCenter - rDelta / aspect;
            i1 = iCenter + rDelta / aspect;

            dr = (r1 - r0) / Width;
            di = (i1 - i0) / Height;

            for (y = 0, i = i0, index = 0; y < Height; y++, i += di)
            {
                for (x = 0, r = r0; x < Width; x++, r += dr)
                {
                    zr = r;
                    zi = i;

                    n = 0;
                    do
                    {
                        // f: z->z^p-1 = exp(p*ln(z))-1
                        // exp(a+ib)=exp(a)*(cos(b)+i*sin(b))
                        // ln(z)=ln|z|+i*arg(z)
                        // exp(p*ln(z))-1 =
                        // = exp((pr+i*pi)*(ln|z|+i*arg(z)))-1 =
                        // = exp(pr*ln|z|-pi*arg(z)+i*(pi*ln|z|+pr*arg(z)))-1 =
                        // = exp(pr*ln|z|-pi*arg(z))*(cos(pi*ln|z|+pr*arg(z))+i*sin(pi*ln|z|+pr*arg(z)))-1

                        lnz  = System.Math.Log(Math.Sqrt(zr * zr + zi * zi));
                        argz = System.Math.Atan2(zi, zr);
                        amp  = System.Math.Exp(pr * lnz - pi * argz);
                        phi  = pi * lnz + pr * argz;

                        zr2 = amp * System.Math.Cos(phi) - 1;
                        zi2 = amp * System.Math.Sin(phi);

                        // f': z->p*z^(p-1) = p*exp((p-1)*ln(z)) =
                        // = (pr+i*pi)*exp((pr-1+i*pi)*(ln|z|+i*arg(z))) =
                        // = (pr+i*pi)*exp((pr-1)*ln|z|-pi*arg(z)+i*(pi*ln|z|+(pr-1)*arg(z))) =
                        // = (pr+i*pi)*exp((pr-1)*ln|z|-pi*arg(z))(sin(pi*ln|z|+(pr-1)*arg(z))+i*cos(pi*ln|z|+(pr-1)*arg(z))) =

                        amp = System.Math.Exp((pr - 1) * lnz - pi * argz);
                        phi = pi * lnz + (pr - 1) * argz;

                        zr3 = amp * System.Math.Cos(phi);
                        zi3 = amp * System.Math.Sin(phi);

                        Temp = pr * zr3 - pi * zi3;
                        zi3  = pr * zi3 + pi * zr3;
                        zr3  = Temp;

                        // f/f':

                        Temp = 1.0 / (zr3 * zr3 + zi3 * zi3);
                        zr4  = (zr2 * zr3 + zi2 * zi3) * Temp;
                        zi4  = (zi2 * zr3 - zr2 * zi3) * Temp;

                        Temp = Rr * zr4 - Ri * zi4;
                        zi4  = Ri * zr4 + Rr * zi4 + i;
                        zr4  = Temp + r;

                        zr -= zr4;
                        zi -= zi4;

                        Temp = Math.Sqrt(zr4 * zr4 + zi4 * zi4);
                    }while ((Temp > Conv) && (Temp < Div) && (n++ < N));

                    if (Temp < Conv && n < N)
                    {
                        rgb[index++] = blues[n];
                        rgb[index++] = greens[n];
                        rgb[index++] = reds[n];
                    }
                    else
                    {
                        rgb[index++] = 0;
                        rgb[index++] = 0;
                        rgb[index++] = 0;
                    }

                    rgb[index++] = 255;
                }
            }

            using (SKData Data = SKData.Create(new MemoryStream(rgb)))
            {
                SKImage Bitmap = SKImage.FromPixelData(new SKImageInfo(Width, Height, SKColorType.Bgra8888), Data, Width * 4);
                return(new FractalGraph(Bitmap, r0, i0, r1, i1, rDelta * 2, true, Node, FractalZoomScript, State));
            }
        }
        public static FractalGraph CalcNewton(double rCenter, double iCenter, double rDelta, Complex R,
                                              ILambdaExpression f, ScriptNode fDef, Variables Variables, SKColor[] Palette,
                                              int Width, int Height, ScriptNode Node, FractalZoomScript FractalZoomScript,
                                              object State)
        {
            byte[]  reds;
            byte[]  greens;
            byte[]  blues;
            double  RRe = R.Real;
            double  RIm = R.Imaginary;
            double  r0, i0, r1, i1;
            double  dr, di;
            double  r, i;
            double  aspect;
            int     x, y;
            int     n, N;
            SKColor cl;
            Complex z;

            N      = Palette.Length;
            reds   = new byte[N];
            greens = new byte[N];
            blues  = new byte[N];

            for (x = 0; x < N; x++)
            {
                cl        = Palette[x];
                reds[x]   = cl.Red;
                greens[x] = cl.Green;
                blues[x]  = cl.Blue;
            }

            Variables v = new Variables();

            Variables.CopyTo(v);

            if (!(f is IDifferentiable Differentiable) ||
                !(Differentiable.Differentiate(Differentiable.DefaultVariableName, v) is ILambdaExpression fPrim))
            {
                throw new ScriptRuntimeException("Lambda expression not differentiable.", Node);
            }

            int    size = Width * Height * 4;
            double Conv = 1e-10;
            double Div  = 1e10;

            byte[] rgb = new byte[size];

            Complex[]  Row;
            Complex[]  Row2;
            Complex[]  Row3;
            int[]      Offset;
            IElement[] P = new IElement[1];
            int        j, c, x2;
            IElement   Obj, Obj2;
            double     Mod;

            rDelta *= 0.5;
            r0      = rCenter - rDelta;
            r1      = rCenter + rDelta;

            aspect = ((double)Width) / Height;

            i0 = iCenter - rDelta / aspect;
            i1 = iCenter + rDelta / aspect;

            dr = (r1 - r0) / Width;
            di = (i1 - i0) / Height;

            for (y = 0, i = i0; y < Height; y++, i += di)
            {
                Row    = new Complex[Width];
                Offset = new int[Width];

                c = Width;
                for (x = 0, x2 = y * Width * 4, r = r0; x < Width; x++, r += dr, x2 += 4)
                {
                    Row[x]    = new Complex(r, i);
                    Offset[x] = x2;
                }

                n = 0;
                while (n < N && c > 0)
                {
                    n++;
                    P[0] = Expression.Encapsulate(Row);
                    Obj  = f.Evaluate(P, v);
                    Obj2 = fPrim.Evaluate(P, v);
                    Row2 = Obj.AssociatedObjectValue as Complex[];
                    Row3 = Obj2.AssociatedObjectValue as Complex[];

                    if (Row2 == null || Row3 == null)
                    {
                        throw new ScriptRuntimeException("Lambda expression (and its first derivative) must be able to accept complex vectors, " +
                                                         "and return complex vectors of equal length. Type returned: " +
                                                         Obj.GetType().FullName + " and " + Obj2.GetType().FullName, Node);
                    }
                    else if (Row2.Length != c || Row3.Length != c)
                    {
                        throw new ScriptRuntimeException("Lambda expression (and its first derivative) must be able to accept complex vectors, " +
                                                         "and return complex vectors of equal length. Length returned: " +
                                                         Row2.Length.ToString() + " and " + Row3.Length.ToString() +
                                                         ". Expected: " + c.ToString(), Node);
                    }

                    for (x = x2 = 0; x < c; x++)
                    {
                        j       = Offset[x];
                        z       = R * Row2[x] / Row3[x];
                        Row[x] -= z;

                        Mod = z.Magnitude;

                        if (Mod > Conv && Mod < Div)
                        {
                            if (x != x2)
                            {
                                Offset[x2] = j;
                            }

                            x2++;
                        }
                        else
                        {
                            if (n >= N)
                            {
                                rgb[j++] = 0;
                                rgb[j++] = 0;
                                rgb[j++] = 0;
                            }
                            else
                            {
                                rgb[j++] = blues[n];
                                rgb[j++] = greens[n];
                                rgb[j++] = reds[n];
                            }

                            rgb[j++] = 255;
                        }
                    }

                    if (x2 < x)
                    {
                        Array.Resize <Complex>(ref Row, x2);
                        Array.Resize <int>(ref Offset, x2);
                        c = x2;
                    }
                }
            }

            using (SKData Data = SKData.Create(new MemoryStream(rgb)))
            {
                SKImage Bitmap = SKImage.FromPixelData(new SKImageInfo(Width, Height, SKColorType.Bgra8888), Data, Width * 4);
                return(new FractalGraph(Bitmap, r0, i0, r1, i1, rDelta * 2, true, Node, FractalZoomScript, State));
            }
        }
        public static FractalGraph CalcNewton(double rCenter, double iCenter, double rDelta, Complex R,
                                              Complex[] Coefficients, SKColor[] Palette, int Width, int Height, ScriptNode Node,
                                              FractalZoomScript FractalZoomScript, object State)
        {
            byte[]  reds;
            byte[]  greens;
            byte[]  blues;
            double  RRe = R.Real;
            double  RIm = R.Imaginary;
            double  r0, i0, r1, i1;
            double  dr, di;
            double  r, i;
            double  zr, zi, zr2, zi2, zr3, zi3, zr4, zi4;
            double  aspect;
            double  Temp;
            int     x, y;
            int     n, N;
            int     index;
            int     Degree = Coefficients.Length - 1;
            SKColor cl;

            N      = Palette.Length;
            reds   = new byte[N];
            greens = new byte[N];
            blues  = new byte[N];

            for (x = 0; x < N; x++)
            {
                cl        = Palette[x];
                reds[x]   = cl.Red;
                greens[x] = cl.Green;
                blues[x]  = cl.Blue;
            }

            if (Degree < 2)
            {
                Array.Resize <Complex>(ref Coefficients, 3);
                while (Degree < 2)
                {
                    Coefficients[++Degree] = Complex.Zero;
                }
            }

            Complex[] Prim = new Complex[Degree];
            for (x = 1; x <= Degree; x++)
            {
                Prim[x - 1] = x * Coefficients[x];
            }

            Array.Reverse(Prim);
            Coefficients = (Complex[])Coefficients.Clone();
            Array.Reverse(Coefficients);

            int j, c = Prim.Length;

            double[] ReC    = new double[c + 1];
            double[] ImC    = new double[c + 1];
            double[] RePrim = new double[c];
            double[] ImPrim = new double[c];
            Complex  z;

            for (j = 0; j < c; j++)
            {
                z      = Coefficients[j];
                ReC[j] = z.Real;
                ImC[j] = z.Imaginary;

                z         = Prim[j];
                RePrim[j] = z.Real;
                ImPrim[j] = z.Imaginary;
            }

            z      = Coefficients[j];
            ReC[j] = z.Real;
            ImC[j] = z.Imaginary;

            int    size = Width * Height * 4;
            double Conv = 1e-10;
            double Div  = 1e10;

            byte[] rgb = new byte[size];

            rDelta *= 0.5;
            r0      = rCenter - rDelta;
            r1      = rCenter + rDelta;

            aspect = ((double)Width) / Height;

            i0 = iCenter - rDelta / aspect;
            i1 = iCenter + rDelta / aspect;

            dr = (r1 - r0) / Width;
            di = (i1 - i0) / Height;

            for (y = 0, i = i0, index = 0; y < Height; y++, i += di)
            {
                for (x = 0, r = r0; x < Width; x++, r += dr)
                {
                    zr = r;
                    zi = i;

                    n = 0;
                    do
                    {
                        // f:
                        zr2 = zi2 = 0;
                        for (j = 0; j <= c; j++)
                        {
                            Temp = zr2 * zr - zi2 * zi + ReC[j];
                            zi2  = zr2 * zi + zi2 * zr + ImC[j];
                            zr2  = Temp;
                        }

                        // f':
                        zr3 = zi3 = 0;
                        for (j = 0; j < c; j++)
                        {
                            Temp = zr3 * zr - zi3 * zi + RePrim[j];
                            zi3  = zr3 * zi + zi3 * zr + ImPrim[j];
                            zr3  = Temp;
                        }

                        // f/f':

                        Temp = 1.0 / (zr3 * zr3 + zi3 * zi3);
                        zr4  = (zr2 * zr3 + zi2 * zi3) * Temp;
                        zi4  = (zi2 * zr3 - zr2 * zi3) * Temp;

                        // R*f/f'
                        Temp = zr4 * RRe - zi4 * RIm;
                        zi4  = zr4 * RIm + zi4 * RRe;
                        zr4  = Temp;

                        zr -= zr4;
                        zi -= zi4;

                        Temp = Math.Sqrt(zr4 * zr4 + zi4 * zi4);
                    }while ((Temp > Conv) && (Temp < Div) && (n++ < N));

                    if (Temp < Conv && n < N)
                    {
                        rgb[index++] = blues[n];
                        rgb[index++] = greens[n];
                        rgb[index++] = reds[n];
                    }
                    else
                    {
                        rgb[index++] = 0;
                        rgb[index++] = 0;
                        rgb[index++] = 0;
                    }

                    rgb[index++] = 255;
                }
            }

            using (SKData Data = SKData.Create(new MemoryStream(rgb)))
            {
                SKImage Bitmap = SKImage.FromPixelData(new SKImageInfo(Width, Height, SKColorType.Bgra8888), Data, Width * 4);
                return(new FractalGraph(Bitmap, r0, i0, r1, i1, rDelta * 2, true, Node, FractalZoomScript, State));
            }
        }
Example #11
0
        public static FractalGraph CalcHalley(double rCenter, double iCenter, double rDelta, Complex R,
                                              double[] Coefficients, SKColor[] Palette, int Width, int Height, ScriptNode Node,
                                              FractalZoomScript FractalZoomScript, object State)
        {
            byte[]  reds;
            byte[]  greens;
            byte[]  blues;
            double  RRe = R.Real;
            double  RIm = R.Imaginary;
            double  r0, i0, r1, i1;
            double  dr, di;
            double  r, i;
            double  zr, zi, zr2, zi2, zr3, zi3, zr4, zi4, zr5, zi5, zr6, zi6;
            double  aspect;
            double  Temp;
            int     x, y;
            int     n, N;
            int     index;
            int     Degree = Coefficients.Length - 1;
            SKColor cl;

            N      = Palette.Length;
            reds   = new byte[N];
            greens = new byte[N];
            blues  = new byte[N];

            for (x = 0; x < N; x++)
            {
                cl        = Palette[x];
                reds[x]   = cl.Red;
                greens[x] = cl.Green;
                blues[x]  = cl.Blue;
            }

            if (Degree < 3)
            {
                Array.Resize <double>(ref Coefficients, 4);
                while (Degree < 3)
                {
                    Coefficients[++Degree] = 0;
                }
            }

            double[] Prim = new double[Degree];
            for (x = 1; x <= Degree; x++)
            {
                Prim[x - 1] = x * Coefficients[x];
            }

            double[] Bis = new double[Degree - 1];
            for (x = 1; x < Degree; x++)
            {
                Bis[x - 1] = x * Prim[x];
            }

            Array.Reverse(Bis);
            Array.Reverse(Prim);
            Coefficients = (double[])Coefficients.Clone();
            Array.Reverse(Coefficients);

            int    size = Width * Height * 4;
            double Conv = 1e-10;
            double Div  = 1e10;

            byte[] rgb = new byte[size];

            rDelta *= 0.5;
            r0      = rCenter - rDelta;
            r1      = rCenter + rDelta;

            aspect = ((double)Width) / Height;

            i0 = iCenter - rDelta / aspect;
            i1 = iCenter + rDelta / aspect;

            dr = (r1 - r0) / Width;
            di = (i1 - i0) / Height;

            for (y = 0, i = i0, index = 0; y < Height; y++, i += di)
            {
                for (x = 0, r = r0; x < Width; x++, r += dr)
                {
                    zr = r;
                    zi = i;

                    n = 0;
                    do
                    {
                        // f:
                        zr2 = zi2 = 0;
                        foreach (double C in Coefficients)
                        {
                            Temp = zr2 * zr - zi2 * zi + C;
                            zi2  = zr2 * zi + zi2 * zr;
                            zr2  = Temp;
                        }

                        // f':
                        zr3 = zi3 = 0;
                        foreach (double C in Prim)
                        {
                            Temp = zr3 * zr - zi3 * zi + C;
                            zi3  = zr3 * zi + zi3 * zr;
                            zr3  = Temp;
                        }

                        // f":
                        zr4 = zi4 = 0;
                        foreach (double C in Bis)
                        {
                            Temp = zr4 * zr - zi4 * zi + C;
                            zi4  = zr4 * zi + zi4 * zr;
                            zr4  = Temp;
                        }

                        // 2*f*f'

                        zr5 = 2 * (zr2 * zr3 - zi2 * zi3);
                        zi5 = 2 * (zr2 * zi3 + zi2 * zr3);

                        // 2f'^2-f*f"

                        zr6 = 2 * (zr3 * zr3 - zi3 * zi3) - (zr2 * zr4 - zi2 * zi4);
                        zi6 = 4 * zr3 * zi3 - (zr2 * zi4 + zr4 * zi2);

                        // R*2*f*f'/2f'^2-f*f"

                        Temp = 1.0 / (zr6 * zr6 + zi6 * zi6);
                        zr4  = (zr5 * zr6 + zi5 * zi6) * Temp;
                        zi4  = (zi5 * zr6 - zr5 * zi6) * Temp;

                        // R*2*f*f'/(2f'^2-f*f")
                        Temp = zr4 * RRe - zi4 * RIm;
                        zi4  = zr4 * RIm + zi4 * RRe;
                        zr4  = Temp;

                        zr -= zr4;
                        zi -= zi4;

                        Temp = Math.Sqrt(zr4 * zr4 + zi4 * zi4);
                    }while ((Temp > Conv) && (Temp < Div) && (n++ < N));

                    if (Temp < Conv && n < N)
                    {
                        rgb[index++] = blues[n];
                        rgb[index++] = greens[n];
                        rgb[index++] = reds[n];
                    }
                    else
                    {
                        rgb[index++] = 0;
                        rgb[index++] = 0;
                        rgb[index++] = 0;
                    }

                    rgb[index++] = 255;
                }
            }

            using (SKData Data = SKData.Create(new MemoryStream(rgb)))
            {
                SKImage Bitmap = SKImage.FromPixelData(new SKImageInfo(Width, Height, SKColorType.Bgra8888), Data, Width * 4);
                return(new FractalGraph(Bitmap, r0, i0, r1, i1, rDelta * 2, true, Node, FractalZoomScript, State));
            }
        }
Example #12
0
        public static FractalGraph CalcIfs(double xCenter, double yCenter, double rDelta, long N,
                                           DoubleMatrix[] Functions, double[] Weights, SKColor[] Colors, int Width, int Height, int Seed,
                                           ScriptNode Node, FractalZoomScript FractalZoomScript, object State)
        {
            DoubleMatrix M;

            double[,] E;
            double[][] Coefficients;
            double     TotWeight = 0;
            double     Weight;
            SKColor    cl;

            byte[] Reds;
            byte[] Greens;
            byte[] Blues;
            int    i, c = Functions.Length;
            Random Gen = new Random(Seed);

            if (c < 2)
            {
                throw new ScriptRuntimeException("At least two transformations need to be provided.", Node);
            }

            if (Weights.Length != c)
            {
                throw new ArgumentException("Weights must be of equal length as Functions.", "Weights");
            }

            if (Colors.Length != c)
            {
                throw new ArgumentException("Colors must be of equal length as Functions.", "Colors");
            }

            for (i = 0; i < c; i++)
            {
                Weight = Weights[i];
                if (Weight < 0)
                {
                    throw new ScriptRuntimeException("Weights must be non-negative.", Node);
                }

                Weights[i] += TotWeight;
                TotWeight  += Weight;
            }

            if (TotWeight == 0)
            {
                throw new ScriptRuntimeException("The total weight of all functions must be postitive.", Node);
            }

            for (i = 0; i < c; i++)
            {
                Weights[i] /= TotWeight;
            }

            Coefficients = new double[c][];
            Reds         = new byte[c];
            Greens       = new byte[c];
            Blues        = new byte[c];

            for (i = 0; i < c; i++)
            {
                cl        = Colors[i];
                Reds[i]   = cl.Red;
                Greens[i] = cl.Green;
                Blues[i]  = cl.Blue;

                M = Functions[i];
                E = M.Values;

                if (M.Columns == 2 && M.Rows == 2)
                {
                    Coefficients[i] = new double[]
                    {
                        (double)E[0, 0], (double)E[0, 1], 0,
                        (double)E[1, 0], (double)E[1, 1], 0,
                        0, 0, 1
                    };
                }
                else if (M.Columns == 3 && M.Rows == 3)
                {
                    Coefficients[i] = new double[]
                    {
                        (double)E[0, 0], (double)E[0, 1], (double)E[0, 2],
                        (double)E[1, 0], (double)E[1, 1], (double)E[1, 2],
                        (double)E[2, 0], (double)E[2, 1], (double)E[2, 2]
                    };
                }
                else
                {
                    throw new ScriptRuntimeException("Matrix not a linear 2D-transformation or a homogenous 2D-transformation.", Node);
                }
            }

            int size = Width * Height * 4;

            byte[] rgb = new byte[size];

            double AspectRatio = ((double)Width) / Height;
            double x = Gen.NextDouble();
            double y = Gen.NextDouble();
            double p = 1;
            double x2, y2, p2;

            double[] C;
            int      j;
            double   xMin, xMax, yMin, yMax;
            double   sx, sy;
            int      xi, yi;

            xMin = xCenter - rDelta / 2;
            xMax = xMin + rDelta;
            yMin = yCenter - rDelta / (2 * AspectRatio);
            yMax = yMin + rDelta / AspectRatio;

            sx = Width / (xMax - xMin);
            sy = Height / (yMax - yMin);

            for (i = 0; i < 20; i++)
            {
                Weight = Gen.NextDouble();
                j      = 0;
                while (j < c - 1 && Weights[j] <= Weight)
                {
                    j++;
                }

                C = Coefficients[j];

                x2 = C[0] * x + C[1] * y + C[2] * p;
                y2 = C[3] * x + C[4] * y + C[5] * p;
                p2 = C[6] * x + C[7] * y + C[8] * p;

                x = x2;
                y = y2;
                p = p2;
            }

            while (N-- > 0)
            {
                Weight = Gen.NextDouble();
                j      = 0;
                while (j < c - 1 && Weights[j] <= Weight)
                {
                    j++;
                }

                C = Coefficients[j];

                x2 = C[0] * x + C[1] * y + C[2] * p;
                y2 = C[3] * x + C[4] * y + C[5] * p;
                p2 = C[6] * x + C[7] * y + C[8] * p;

                x = x2;
                y = y2;
                p = p2;

                if (p == 0)
                {
                    break;
                }

                if (x < xMin || x > xMax || y < yMin || y > yMax)
                {
                    continue;
                }

                xi = (int)((x / p - xMin) * sx + 0.5);
                yi = Height - 1 - (int)((y / p - yMin) * sy + 0.5);

                if (xi < 0 || xi >= Width || yi < 0 || yi >= Height)
                {
                    continue;
                }

                i = (yi * Width + xi) << 2;

                if (rgb[i + 3] == 0)
                {
                    rgb[i++] = Blues[j];
                    rgb[i++] = Greens[j];
                    rgb[i++] = Reds[j];
                    rgb[i]   = 0xff;
                }
                else
                {
                    rgb[i] = (byte)((rgb[i] + Blues[j]) >> 1);
                    i++;
                    rgb[i] = (byte)((rgb[i] + Greens[j]) >> 1);
                    i++;
                    rgb[i] = (byte)((rgb[i] + Reds[j]) >> 1);
                }
            }

            using (SKData Data = SKData.Create(new MemoryStream(rgb)))
            {
                SKImage Bitmap = SKImage.FromPixelData(new SKImageInfo(Width, Height, SKColorType.Bgra8888), Data, Width * 4);
                return(new FractalGraph(Bitmap, xMin, yMin, xMax, yMax, rDelta, false, Node, FractalZoomScript, State));
            }
        }
Example #13
0
        public static FractalGraph CalcJulia(double rCenter, double iCenter, ILambdaExpression f,
                                             ScriptNode fDef, double rDelta, SKColor[] Palette, int Width, int Height,
                                             ScriptNode Node, Variables Variables,
                                             FractalZoomScript FractalZoomScript, object State)
        {
            byte[]  reds;
            byte[]  greens;
            byte[]  blues;
            double  r0, i0, r1, i1;
            double  dr, di;
            double  r, i, Mod;
            double  aspect;
            int     x, x2, y;
            int     n, N;
            SKColor cl;

            N      = Palette.Length;
            reds   = new byte[N];
            greens = new byte[N];
            blues  = new byte[N];

            for (x = 0; x < N; x++)
            {
                cl        = Palette[x];
                reds[x]   = cl.Red;
                greens[x] = cl.Green;
                blues[x]  = cl.Blue;
            }

            int size = Width * Height * 4;

            byte[]  rgb = new byte[size];
            Complex z;

            IElement[] P = new IElement[1];
            int        j, c;
            IElement   Obj;

            rDelta *= 0.5;
            r0      = rCenter - rDelta;
            r1      = rCenter + rDelta;

            aspect = ((double)Width) / Height;

            i0 = iCenter - rDelta / aspect;
            i1 = iCenter + rDelta / aspect;

            dr = (r1 - r0) / Width;
            di = (i1 - i0) / Height;

            for (y = 0, i = i0; y < Height; y++, i += di)
            {
                Complex[] Row    = new Complex[Width];
                int[]     Offset = new int[Width];

                c = Width;
                for (x = 0, x2 = y * Width * 4, r = r0; x < Width; x++, r += dr, x2 += 4)
                {
                    Row[x]    = new Complex(r, i);
                    Offset[x] = x2;
                }

                Variables v = new Variables();
                Variables.CopyTo(v);

                n = 0;
                while (n < N && c > 0)
                {
                    n++;
                    P[0] = Expression.Encapsulate(Row);
                    Obj  = f.Evaluate(P, v);
                    Row  = Obj.AssociatedObjectValue as Complex[];

                    if (Row == null)
                    {
                        throw new ScriptRuntimeException("Lambda expression must be able to accept complex vectors, " +
                                                         "and return complex vectors of equal length. Type returned: " +
                                                         Obj.GetType().FullName, Node);
                    }
                    else if (Row.Length != c)
                    {
                        throw new ScriptRuntimeException("Lambda expression must be able to accept complex vectors, " +
                                                         "and return complex vectors of equal length. Length returned: " +
                                                         Row.Length.ToString() + ". Expected: " + c.ToString(), Node);
                    }

                    for (x = x2 = 0; x < c; x++)
                    {
                        z = Row[x];
                        j = Offset[x];

                        Mod = z.Magnitude;

                        if (Mod < 3)
                        {
                            if (x != x2)
                            {
                                Row[x2]    = z;
                                Offset[x2] = j;
                            }

                            x2++;
                        }
                        else
                        {
                            if (n >= N)
                            {
                                rgb[j++] = 0;
                                rgb[j++] = 0;
                                rgb[j++] = 0;
                            }
                            else
                            {
                                rgb[j++] = blues[n];
                                rgb[j++] = greens[n];
                                rgb[j++] = reds[n];
                            }

                            rgb[j++] = 255;
                        }
                    }

                    if (x2 < x)
                    {
                        Array.Resize <Complex>(ref Row, x2);
                        Array.Resize <int>(ref Offset, x2);
                        c = x2;
                    }
                }

                if (c > 0)
                {
                    for (x = 0; x < c; x++)
                    {
                        j = Offset[x];

                        rgb[j++] = 0;
                        rgb[j++] = 0;
                        rgb[j++] = 0;
                        rgb[j++] = 255;
                    }
                }
            }

            using (SKData Data = SKData.Create(new MemoryStream(rgb)))
            {
                SKImage Bitmap = SKImage.FromPixelData(new SKImageInfo(Width, Height, SKColorType.Bgra8888), Data, Width * 4);
                return(new FractalGraph(Bitmap, r0, i0, r1, i1, rDelta * 2, true, Node, FractalZoomScript, State));
            }
        }
Example #14
0
        public static SKImage ToBitmap(double[] ColorIndex, int Width, int Height, SKColor[] Palette)
        {
            int N     = Palette.Length;
            int Size  = Width * Height;
            int Size4 = Size * 4;

            byte[]  rgb = new byte[Size4];
            byte[]  reds;
            byte[]  greens;
            byte[]  blues;
            double  d;
            SKColor cl;
            int     Index2;
            int     ci;
            int     Component;
            int     Index;
            int     x;

            reds   = new byte[N];
            greens = new byte[N];
            blues  = new byte[N];

            for (x = 0; x < N; x++)
            {
                cl        = Palette[x];
                reds[x]   = cl.Red;
                greens[x] = cl.Green;
                blues[x]  = cl.Blue;
            }

            for (Index = Index2 = 0; Index < Size; Index++)
            {
                d = ColorIndex[Index];

                ci = (int)d;
                if (ci < 0 || ci >= N)
                {
                    rgb[Index2++] = 0;
                    rgb[Index2++] = 0;
                    rgb[Index2++] = 0;
                    rgb[Index2++] = 255;
                }
                else if (ci == N - 1)
                {
                    rgb[Index2++] = blues[ci];
                    rgb[Index2++] = greens[ci];
                    rgb[Index2++] = reds[ci];
                    rgb[Index2++] = 255;
                }
                else
                {
                    d -= ci;

                    Component = (int)(blues[ci + 1] * d + blues[ci] * (1 - d) + 0.5);
                    if (Component > 255)
                    {
                        rgb[Index2++] = 255;
                    }
                    else
                    {
                        rgb[Index2++] = (byte)Component;
                    }

                    Component = (int)(greens[ci + 1] * d + greens[ci] * (1 - d) + 0.5);
                    if (Component > 255)
                    {
                        rgb[Index2++] = 255;
                    }
                    else
                    {
                        rgb[Index2++] = (byte)Component;
                    }

                    Component = (int)(reds[ci + 1] * d + reds[ci] * (1 - d) + 0.5);
                    if (Component > 255)
                    {
                        rgb[Index2++] = 255;
                    }
                    else
                    {
                        rgb[Index2++] = (byte)Component;
                    }

                    rgb[Index2++] = 255;
                }
            }

            using (SKData Data = SKData.Create(new MemoryStream(rgb)))
            {
                return(SKImage.FromPixelData(new SKImageInfo(Width, Height, SKColorType.Bgra8888), Data, Width * 4));
            }
        }
Example #15
0
        public static FractalGraph CalcNewton(double rCenter, double iCenter, double rDelta, Complex R,
                                              ILambdaExpression f, ScriptNode fDef, Variables Variables, int N, int Width, int Height,
                                              ScriptNode Node, FractalZoomScript FractalZoomScript, object State)
        {
            double        RRe             = R.Real;
            double        RIm             = R.Imaginary;
            List <double> AttractorsR     = new List <double>();
            List <double> AttractorsI     = new List <double>();
            List <int>    AttractorColors = new List <int>();

            double[] AttractorsR2 = new double[0];
            double[] AttractorsI2 = new double[0];
            int[]    AttractorsColors2 = new int[0];
            double   r0, i0, r1, i1;
            double   dr, di;
            double   r, i;
            double   zr, zi;
            double   aspect;
            int      x, y, b, c, d;
            int      NrAttractors = 0;
            int      n;
            int      index;

            Variables v = new Variables();

            Variables.CopyTo(v);

            if (!(f is IDifferentiable Differentiable) ||
                !(Differentiable.Differentiate(Differentiable.DefaultVariableName, v) is ILambdaExpression fPrim))
            {
                throw new ScriptRuntimeException("Lambda expression not differentiable.", Node);
            }

            int    size  = Width * Height * 4;
            double Conv  = 1e-10;
            double Div   = 1e10;
            double Conv2 = Conv * 2;

            byte[] rgb = new byte[size];

            Complex[]  Row;
            Complex[]  Row2;
            Complex[]  Row3;
            int[]      Offset;
            IElement[] P = new IElement[1];
            int        j, x2;
            IElement   Obj, Obj2;
            double     Mod;
            Complex    z;

            rDelta *= 0.5;
            r0      = rCenter - rDelta;
            r1      = rCenter + rDelta;

            aspect = ((double)Width) / Height;

            i0 = iCenter - rDelta / aspect;
            i1 = iCenter + rDelta / aspect;

            dr = (r1 - r0) / Width;
            di = (i1 - i0) / Height;

            for (y = 0, i = i0, index = 0; y < Height; y++, i += di)
            {
                Row    = new Complex[Width];
                Offset = new int[Width];

                c = Width;
                for (x = 0, x2 = y * Width * 4, r = r0; x < Width; x++, r += dr, x2 += 4)
                {
                    Row[x]    = new Complex(r, i);
                    Offset[x] = x2;
                }

                n = 0;
                while (n < N && c > 0)
                {
                    n++;
                    P[0] = Expression.Encapsulate(Row);
                    Obj  = f.Evaluate(P, v);
                    Obj2 = fPrim.Evaluate(P, v);
                    Row2 = Obj.AssociatedObjectValue as Complex[];
                    Row3 = Obj2.AssociatedObjectValue as Complex[];

                    if (Row2 == null || Row3 == null)
                    {
                        throw new ScriptRuntimeException("Lambda expression (and its first derivative) must be able to accept complex vectors, " +
                                                         "and return complex vectors of equal length. Type returned: " +
                                                         Obj.GetType().FullName + " and " + Obj2.GetType().FullName, Node);
                    }
                    else if (Row2.Length != c || Row3.Length != c)
                    {
                        throw new ScriptRuntimeException("Lambda expression (and its first derivative) must be able to accept complex vectors, " +
                                                         "and return complex vectors of equal length. Length returned: " +
                                                         Row2.Length.ToString() + " and " + Row3.Length.ToString() +
                                                         ". Expected: " + c.ToString(), Node);
                    }

                    for (x = x2 = 0; x < c; x++)
                    {
                        j       = Offset[x];
                        z       = R * Row2[x] / Row3[x];
                        Row[x] -= z;

                        Mod = z.Magnitude;

                        if (Mod > Conv && Mod < Div)
                        {
                            if (x != x2)
                            {
                                Offset[x2] = j;
                            }

                            x2++;
                        }
                        else
                        {
                            if (n >= N)
                            {
                                rgb[j++] = 0;
                                rgb[j++] = 0;
                                rgb[j++] = 0;
                            }
                            else
                            {
                                zr = z.Real;
                                zi = z.Imaginary;

                                for (b = 0; b < NrAttractors; b++)
                                {
                                    if (Math.Abs(AttractorsR2[b] - zr) < Conv2 &&
                                        Math.Abs(AttractorsI2[b] - zi) < Conv2)
                                    {
                                        break;
                                    }
                                }

                                if (b == NrAttractors)
                                {
                                    AttractorsR.Add(zr);
                                    AttractorsI.Add(zi);

                                    int p1 = ~((b % 6) + 1);
                                    int p2 = ((b / 6) % 7);

                                    int Red   = (p1 & 1) != 0 ? 255 : 0;
                                    int Green = (p1 & 2) != 0 ? 255 : 0;
                                    int Blue  = (p1 & 4) != 0 ? 255 : 0;

                                    if ((p2 & 1) != 0)
                                    {
                                        Red >>= 1;
                                    }

                                    if ((p2 & 2) != 0)
                                    {
                                        Green >>= 1;
                                    }

                                    if ((p2 & 4) != 0)
                                    {
                                        Blue >>= 1;
                                    }

                                    Blue <<= 8;
                                    Blue  |= Green;
                                    Blue <<= 8;
                                    Blue  |= Red;

                                    AttractorColors.Add(Blue);

                                    AttractorsR2      = AttractorsR.ToArray();
                                    AttractorsI2      = AttractorsI.ToArray();
                                    AttractorsColors2 = AttractorColors.ToArray();

                                    NrAttractors++;
                                }

                                b = AttractorColors[b];

                                d            = (byte)b;
                                rgb[index++] = (byte)((d * (N - n + 1)) / N);
                                b          >>= 8;
                                d            = (byte)b;
                                rgb[index++] = (byte)((d * (N - n + 1)) / N);
                                b          >>= 8;
                                d            = (byte)b;
                                rgb[index++] = (byte)((d * (N - n + 1)) / N);
                            }

                            rgb[j++] = 255;
                        }
                    }

                    if (x2 < x)
                    {
                        Array.Resize <Complex>(ref Row, x2);
                        Array.Resize <int>(ref Offset, x2);
                        c = x2;
                    }
                }
            }

            using (SKData Data = SKData.Create(new MemoryStream(rgb)))
            {
                SKImage Bitmap = SKImage.FromPixelData(new SKImageInfo(Width, Height, SKColorType.Bgra8888), Data, Width * 4);
                return(new FractalGraph(Bitmap, r0, i0, r1, i1, rDelta * 2, true, Node, FractalZoomScript, State));
            }
        }
Example #16
0
        public static FractalGraph CalcNewton(double rCenter, double iCenter, double rDelta, Complex R,
                                              Complex[] Coefficients, int N, int Width, int Height, ScriptNode Node,
                                              FractalZoomScript FractalZoomScript, object State)
        {
            double        RRe             = R.Real;
            double        RIm             = R.Imaginary;
            List <double> AttractorsR     = new List <double>();
            List <double> AttractorsI     = new List <double>();
            List <int>    AttractorColors = new List <int>();

            double[] AttractorsR2 = new double[0];
            double[] AttractorsI2 = new double[0];
            int[]    AttractorsColors2 = new int[0];
            double   r0, i0, r1, i1;
            double   dr, di;
            double   r, i;
            double   zr, zi, zr2, zi2, zr3, zi3, zr4, zi4;
            double   aspect;
            double   Temp;
            int      x, y, b, c = 0, d;
            int      n;
            int      index;
            int      Degree = Coefficients.Length - 1;

            if (Degree < 2)
            {
                Array.Resize <Complex>(ref Coefficients, 3);
                while (Degree < 2)
                {
                    Coefficients[++Degree] = Complex.Zero;
                }
            }

            Complex[] Prim = new Complex[Degree];
            for (x = 1; x <= Degree; x++)
            {
                Prim[x - 1] = x * Coefficients[x];
            }

            Array.Reverse(Prim);
            Coefficients = (Complex[])Coefficients.Clone();
            Array.Reverse(Coefficients);

            int j, e = Prim.Length;

            double[] ReC    = new double[e + 1];
            double[] ImC    = new double[e + 1];
            double[] RePrim = new double[e];
            double[] ImPrim = new double[e];
            Complex  z;

            for (j = 0; j < e; j++)
            {
                z      = Coefficients[j];
                ReC[j] = z.Real;
                ImC[j] = z.Imaginary;

                z         = Prim[j];
                RePrim[j] = z.Real;
                ImPrim[j] = z.Imaginary;
            }

            z      = Coefficients[j];
            ReC[j] = z.Real;
            ImC[j] = z.Imaginary;

            int    size  = Width * Height * 4;
            double Conv  = 1e-10;
            double Div   = 1e10;
            double Conv2 = Conv * 2;

            byte[] rgb = new byte[size];

            rDelta *= 0.5;
            r0      = rCenter - rDelta;
            r1      = rCenter + rDelta;

            aspect = ((double)Width) / Height;

            i0 = iCenter - rDelta / aspect;
            i1 = iCenter + rDelta / aspect;

            dr = (r1 - r0) / Width;
            di = (i1 - i0) / Height;

            for (y = 0, i = i0, index = 0; y < Height; y++, i += di)
            {
                for (x = 0, r = r0; x < Width; x++, r += dr)
                {
                    zr = r;
                    zi = i;

                    n = 0;
                    do
                    {
                        // f:
                        zr2 = zi2 = 0;
                        for (j = 0; j <= e; j++)
                        {
                            Temp = zr2 * zr - zi2 * zi + ReC[j];
                            zi2  = zr2 * zi + zi2 * zr + ImC[j];
                            zr2  = Temp;
                        }

                        // f':
                        zr3 = zi3 = 0;
                        for (j = 0; j < e; j++)
                        {
                            Temp = zr3 * zr - zi3 * zi + RePrim[j];
                            zi3  = zr3 * zi + zi3 * zr + ImPrim[j];
                            zr3  = Temp;
                        }

                        // f/f':

                        Temp = 1.0 / (zr3 * zr3 + zi3 * zi3);
                        zr4  = (zr2 * zr3 + zi2 * zi3) * Temp;
                        zi4  = (zi2 * zr3 - zr2 * zi3) * Temp;

                        // R*f/f'
                        Temp = zr4 * RRe - zi4 * RIm;
                        zi4  = zr4 * RIm + zi4 * RRe;
                        zr4  = Temp;

                        zr -= zr4;
                        zi -= zi4;

                        Temp = Math.Sqrt(zr4 * zr4 + zi4 * zi4);
                    }while ((Temp > Conv) && (Temp < Div) && (n++ < N));

                    if (Temp < Conv && n < N)
                    {
                        for (b = 0; b < c; b++)
                        {
                            if (Math.Abs(AttractorsR2[b] - zr) < Conv2 &&
                                Math.Abs(AttractorsI2[b] - zi) < Conv2)
                            {
                                break;
                            }
                        }

                        if (b == c)
                        {
                            AttractorsR.Add(zr);
                            AttractorsI.Add(zi);

                            int p1 = ~((b % 6) + 1);
                            int p2 = ((b / 6) % 7);

                            int Red   = (p1 & 1) != 0 ? 255 : 0;
                            int Green = (p1 & 2) != 0 ? 255 : 0;
                            int Blue  = (p1 & 4) != 0 ? 255 : 0;

                            if ((p2 & 1) != 0)
                            {
                                Red >>= 1;
                            }

                            if ((p2 & 2) != 0)
                            {
                                Green >>= 1;
                            }

                            if ((p2 & 4) != 0)
                            {
                                Blue >>= 1;
                            }

                            Blue <<= 8;
                            Blue  |= Green;
                            Blue <<= 8;
                            Blue  |= Red;

                            AttractorColors.Add(Blue);

                            AttractorsR2      = AttractorsR.ToArray();
                            AttractorsI2      = AttractorsI.ToArray();
                            AttractorsColors2 = AttractorColors.ToArray();

                            c++;
                        }

                        b = AttractorColors[b];

                        d            = (byte)b;
                        rgb[index++] = (byte)((d * (N - n + 1)) / N);
                        b          >>= 8;
                        d            = (byte)b;
                        rgb[index++] = (byte)((d * (N - n + 1)) / N);
                        b          >>= 8;
                        d            = (byte)b;
                        rgb[index++] = (byte)((d * (N - n + 1)) / N);
                    }
                    else
                    {
                        rgb[index++] = 0;
                        rgb[index++] = 0;
                        rgb[index++] = 0;
                    }

                    rgb[index++] = 255;
                }
            }

            using (SKData Data = SKData.Create(new MemoryStream(rgb)))
            {
                SKImage Bitmap = SKImage.FromPixelData(new SKImageInfo(Width, Height, SKColorType.Bgra8888), Data, Width * 4);
                return(new FractalGraph(Bitmap, r0, i0, r1, i1, rDelta * 2, true, Node, FractalZoomScript, State));
            }
        }
Example #17
0
        public static FractalGraph CalcIfs(double xCenter, double yCenter, double rDelta, long N,
                                           ILambdaExpression[] Functions, double[] Weights, SKColor[] Colors, int Width, int Height, int Seed,
                                           ScriptNode Node, Variables Variables, FractalZoomScript FractalZoomScript, object State)
        {
            ILambdaExpression Lambda;
            double            TotWeight = 0;
            double            Weight;

            bool[]  Real;
            byte[]  Reds;
            byte[]  Greens;
            byte[]  Blues;
            SKColor cl;
            int     i, c = Functions.Length;
            Random  Gen = new Random(Seed);

            if (c < 2)
            {
                throw new ScriptRuntimeException("At least two transformations need to be provided.", Node);
            }

            if (Weights.Length != c)
            {
                throw new ArgumentException("Weights must be of equal length as Functions.", "Weights");
            }

            if (Colors.Length != c)
            {
                throw new ArgumentException("Colors must be of equal length as Functions.", "Colors");
            }

            for (i = 0; i < c; i++)
            {
                Weight = Weights[i];
                if (Weight < 0)
                {
                    throw new ScriptRuntimeException("Weights must be non-negative.", Node);
                }

                Weights[i] += TotWeight;
                TotWeight  += Weight;
            }

            if (TotWeight == 0)
            {
                throw new ScriptRuntimeException("The total weight of all functions must be postitive.", Node);
            }

            for (i = 0; i < c; i++)
            {
                Weights[i] /= TotWeight;
            }

            Real   = new bool[c];
            Reds   = new byte[c];
            Greens = new byte[c];
            Blues  = new byte[c];

            for (i = 0; i < c; i++)
            {
                cl        = Colors[i];
                Reds[i]   = cl.Red;
                Greens[i] = cl.Green;
                Blues[i]  = cl.Blue;

                Lambda = Functions[i];

                switch (Lambda.NrArguments)
                {
                case 1:
                    Real[i] = false;
                    break;

                case 2:
                    Real[i] = true;
                    break;

                default:
                    throw new ScriptRuntimeException("Lambda expressions in calls to IfsFractal() must be either real-values (taking two parameters) or complex valued (taking one parameter).", Node);
                }
            }

            int size = Width * Height * 4;

            byte[] rgb = new byte[size];

            double        AspectRatio = ((double)Width) / Height;
            double        x           = Gen.NextDouble();
            double        y           = Gen.NextDouble();
            int           j;
            double        xMin, xMax, yMin, yMax;
            double        sx, sy;
            DoubleNumber  xv = new DoubleNumber(0);
            DoubleNumber  yv = new DoubleNumber(0);
            ComplexNumber zv = new ComplexNumber(0);

            IElement[] RealParameters    = new IElement[] { xv, yv };
            IElement[] ComplexParameters = new IElement[] { zv };
            Variables  v = new Variables();
            int        xi, yi;

            Variables.CopyTo(v);

            xMin = xCenter - rDelta / 2;
            xMax = xMin + rDelta;
            yMin = yCenter - rDelta / (2 * AspectRatio);
            yMax = yMin + rDelta / AspectRatio;

            sx = Width / (xMax - xMin);
            sy = Height / (yMax - yMin);

            Complex z;

            for (i = 0; i < 20; i++)
            {
                Weight = Gen.NextDouble();
                j      = 0;
                while (j < c - 1 && Weights[j] <= Weight)
                {
                    j++;
                }

                Lambda = Functions[j];

                if (Real[j])
                {
                    xv.Value = x;
                    yv.Value = y;

                    if (!(Lambda.Evaluate(RealParameters, v) is IVector Result) || Result.Dimension != 2)
                    {
                        throw new ScriptRuntimeException("Expected 2-dimensional numeric vector as a result.", Node);
                    }

                    x = Expression.ToDouble(Result.GetElement(0).AssociatedObjectValue);
                    y = Expression.ToDouble(Result.GetElement(1).AssociatedObjectValue);
                }
                else
                {
                    zv.Value = new Complex(x, y);
                    z        = Expression.ToComplex(Lambda.Evaluate(ComplexParameters, v).AssociatedObjectValue);

                    x = z.Real;
                    y = z.Imaginary;
                }
            }

            while (N-- > 0)
            {
                Weight = Gen.NextDouble();
                j      = 0;
                while (j < c - 1 && Weights[j] <= Weight)
                {
                    j++;
                }

                Lambda = Functions[j];

                if (Real[j])
                {
                    xv.Value = x;
                    yv.Value = y;

                    if (!(Lambda.Evaluate(RealParameters, v) is IVector Result) || Result.Dimension != 2)
                    {
                        throw new ScriptRuntimeException("Expected 2-dimensional numeric vector as a result.", Node);
                    }

                    x = Expression.ToDouble(Result.GetElement(0).AssociatedObjectValue);
                    y = Expression.ToDouble(Result.GetElement(1).AssociatedObjectValue);
                }
                else
                {
                    zv.Value = new Complex(x, y);
                    z        = Expression.ToComplex(Lambda.Evaluate(ComplexParameters, v).AssociatedObjectValue);

                    x = z.Real;
                    y = z.Imaginary;
                }

                if (x < xMin || x > xMax || y < yMin || y > yMax)
                {
                    continue;
                }

                xi = (int)((x - xMin) * sx + 0.5);
                yi = Height - 1 - (int)((y - yMin) * sy + 0.5);

                if (xi < 0 || xi >= Width || yi < 0 || yi >= Height)
                {
                    continue;
                }

                i = (yi * Width + xi) << 2;

                if (rgb[i + 3] == 0)
                {
                    rgb[i++] = Blues[j];
                    rgb[i++] = Greens[j];
                    rgb[i++] = Reds[j];
                    rgb[i]   = 0xff;
                }
                else
                {
                    rgb[i] = (byte)((rgb[i] + Blues[j]) >> 1);
                    i++;
                    rgb[i] = (byte)((rgb[i] + Greens[j]) >> 1);
                    i++;
                    rgb[i] = (byte)((rgb[i] + Reds[j]) >> 1);
                }
            }

            using (SKData Data = SKData.Create(new MemoryStream(rgb)))
            {
                SKImage Bitmap = SKImage.FromPixelData(new SKImageInfo(Width, Height, SKColorType.Bgra8888), Data, Width * 4);
                return(new FractalGraph(Bitmap, xMin, yMin, xMax, yMax, rDelta, false, Node, FractalZoomScript, State));
            }
        }
Example #18
0
        private static void ConvertFile(string file)
        {
            SKColorType colorType;

            using (var image = Pfim.FromFile(file))
            {
                var newData    = image.Data;
                var newDataLen = image.DataLen;
                var stride     = image.Stride;
                switch (image.Format)
                {
                case ImageFormat.Rgb8:
                    colorType = SKColorType.Gray8;
                    break;

                case ImageFormat.R5g6b5:
                    // color channels still need to be swapped
                    colorType = SKColorType.Rgb565;
                    break;

                case ImageFormat.Rgba16:
                    // color channels still need to be swapped
                    colorType = SKColorType.Argb4444;
                    break;

                case ImageFormat.Rgb24:
                    // Skia has no 24bit pixels, so we upscale to 32bit
                    var pixels = image.DataLen / 3;
                    newDataLen = pixels * 4;
                    newData    = new byte[newDataLen];
                    for (int i = 0; i < pixels; i++)
                    {
                        newData[i * 4]     = image.Data[i * 3];
                        newData[i * 4 + 1] = image.Data[i * 3 + 1];
                        newData[i * 4 + 2] = image.Data[i * 3 + 2];
                        newData[i * 4 + 3] = 255;
                    }

                    stride    = image.Width * 4;
                    colorType = SKColorType.Bgra8888;
                    break;

                case ImageFormat.Rgba32:
                    colorType = SKColorType.Bgra8888;
                    break;

                default:
                    throw new ArgumentException($"Skia unable to interpret pfim format: {image.Format}");
                }

                var imageInfo = new SKImageInfo(image.Width, image.Height, colorType);
                var handle    = GCHandle.Alloc(newData, GCHandleType.Pinned);
                var ptr       = Marshal.UnsafeAddrOfPinnedArrayElement(newData, 0);
                using (var data = SKData.Create(ptr, newDataLen, (address, context) => handle.Free()))
                    using (var skImage = SKImage.FromPixelData(imageInfo, data, stride))
                        using (var bitmap = SKBitmap.FromImage(skImage))
                            using (var fs = File.Create(Path.ChangeExtension(file, ".png")))
                                using (var wstream = new SKManagedWStream(fs))
                                {
                                    var success = SKPixmap.Encode(wstream, bitmap, SKEncodedImageFormat.Png, 95);
                                    Console.WriteLine(success ? "Image converted successfully" : "Image unsuccessful");
                                }
            }
        }
Example #19
0
        public static FractalGraph CalcJulia(double rCenter, double iCenter, double R0, double I0, double rDelta,
                                             SKColor[] Palette, int Width, int Height, ScriptNode Node,
                                             FractalZoomScript FractalZoomScript, object State)
        {
            byte[]  reds;
            byte[]  greens;
            byte[]  blues;
            double  r0, i0, r1, i1;
            double  dr, di;
            double  r, i;
            double  zr, zi, zrt, zr2, zi2;
            double  aspect;
            int     x, y;
            int     n, N;
            int     index;
            SKColor cl;

            N      = Palette.Length;
            reds   = new byte[N];
            greens = new byte[N];
            blues  = new byte[N];

            for (x = 0; x < N; x++)
            {
                cl        = Palette[x];
                reds[x]   = cl.Red;
                greens[x] = cl.Green;
                blues[x]  = cl.Blue;
            }

            int size = Width * Height * 4;

            byte[] rgb = new byte[size];

            rDelta *= 0.5;
            r0      = rCenter - rDelta;
            r1      = rCenter + rDelta;

            aspect = ((double)Width) / Height;

            i0 = iCenter - rDelta / aspect;
            i1 = iCenter + rDelta / aspect;

            dr = (r1 - r0) / Width;
            di = (i1 - i0) / Height;

            for (y = 0, i = i0, index = 0; y < Height; y++, i += di)
            {
                for (x = 0, r = r0; x < Width; x++, r += dr)
                {
                    zr = r;
                    zi = i;

                    n   = 0;
                    zr2 = zr * zr;
                    zi2 = zi * zi;

                    while (zr2 + zi2 < 9 && n < N)
                    {
                        n++;
                        zrt = zr2 - zi2 + R0;
                        zi  = 2 * zr * zi + I0;
                        zr  = zrt;

                        zr2 = zr * zr;
                        zi2 = zi * zi;
                    }

                    if (n >= N)
                    {
                        rgb[index++] = 0;
                        rgb[index++] = 0;
                        rgb[index++] = 0;
                    }
                    else
                    {
                        rgb[index++] = blues[n];
                        rgb[index++] = greens[n];
                        rgb[index++] = reds[n];
                    }

                    rgb[index++] = 255;
                }
            }

            using (SKData Data = SKData.Create(new MemoryStream(rgb)))
            {
                SKImage Bitmap = SKImage.FromPixelData(new SKImageInfo(Width, Height, SKColorType.Bgra8888), Data, Width * 4);
                return(new FractalGraph(Bitmap, r0, i0, r1, i1, rDelta * 2, true, Node, FractalZoomScript, State));
            }
        }
Example #20
0
        /// <summary>
        /// Blends two images of the same size using a blending factor.
        /// </summary>
        /// <param name="Image1">Image 1</param>
        /// <param name="Image2">Image 2</param>
        /// <param name="p">Blending factor (0=<paramref name="Image1"/>, 1=<paramref name="Image2"/>).</param>
        /// <returns>Blended image.</returns>
        public static SKImage BlendColors(SKImage Image1, SKImage Image2, double p)
        {
            if (Image1.Width != Image2.Width || Image1.Height != Image2.Height)
            {
                throw new ArgumentException("Images not of the same size.", nameof(Image2));
            }

            SKImageInfo ImageInfo = new SKImageInfo(Image1.Width, Image1.Height, SKColorType.Bgra8888);
            int         i, j, c = ImageInfo.BytesSize;
            IntPtr      Pixels1 = Marshal.AllocCoTaskMem(c);
            IntPtr      Pixels2 = IntPtr.Zero;

            try
            {
                Pixels2 = Marshal.AllocCoTaskMem(c);

                Image1.ReadPixels(ImageInfo, Pixels1, ImageInfo.RowBytes, 0, 0);
                Image2.ReadPixels(ImageInfo, Pixels2, ImageInfo.RowBytes, 0, 0);

                byte[] Bin1 = new byte[c];
                byte[] Bin2 = new byte[c];
                Marshal.Copy(Pixels1, Bin1, 0, c);
                Marshal.Copy(Pixels2, Bin2, 0, c);

                for (i = 0; i < c; i++)
                {
                    j = (int)(Bin1[i] * (1 - p) + Bin2[i] * p + 0.5);
                    if (j < 0)
                    {
                        Bin1[i] = 0;
                    }
                    else if (j > 255)
                    {
                        Bin1[i] = 255;
                    }
                    else
                    {
                        Bin1[i] = (byte)j;
                    }
                }

                Marshal.Copy(Bin1, 0, Pixels1, c);

                using (SKData Data = SKData.Create(Pixels1, c))
                {
                    SKImage Result = SKImage.FromPixelData(new SKImageInfo(ImageInfo.Width, ImageInfo.Height, SKColorType.Bgra8888), Data, ImageInfo.RowBytes);
                    Pixels1 = IntPtr.Zero;

                    return(Result);
                }
            }
            finally
            {
                if (Pixels1 != IntPtr.Zero)
                {
                    Marshal.FreeCoTaskMem(Pixels1);
                }

                if (Pixels2 != IntPtr.Zero)
                {
                    Marshal.FreeCoTaskMem(Pixels2);
                }
            }
        }
Example #21
0
        /// <summary>
        /// Blends an image with a fixed color using a blending factor.
        /// </summary>
        /// <param name="Image">Image</param>
        /// <param name="Color">Color</param>
        /// <param name="p">Blending factor (0=<paramref name="Image"/>, 1=<paramref name="Color"/>).</param>
        /// <returns>Blended image.</returns>
        public static SKImage BlendColors(SKImage Image, SKColor Color, double p)
        {
            SKImageInfo ImageInfo = new SKImageInfo(Image.Width, Image.Height, SKColorType.Bgra8888);
            int         i, j, c = ImageInfo.BytesSize;
            byte        R      = Color.Red;
            byte        G      = Color.Green;
            byte        B      = Color.Blue;
            byte        A      = Color.Alpha;
            IntPtr      Pixels = Marshal.AllocCoTaskMem(c);

            try
            {
                Image.ReadPixels(ImageInfo, Pixels, ImageInfo.RowBytes, 0, 0);

                byte[] Bin = new byte[c];
                Marshal.Copy(Pixels, Bin, 0, c);

                for (i = 0; i < c; i++)
                {
                    j = (int)(Bin[i] * (1 - p) + B * p + 0.5);
                    if (j < 0)
                    {
                        Bin[i] = 0;
                    }
                    else if (j > 255)
                    {
                        Bin[i] = 255;
                    }
                    else
                    {
                        Bin[i] = (byte)j;
                    }

                    j = (int)(Bin[++i] * (1 - p) + G * p + 0.5);
                    if (j < 0)
                    {
                        Bin[i] = 0;
                    }
                    else if (j > 255)
                    {
                        Bin[i] = 255;
                    }
                    else
                    {
                        Bin[i] = (byte)j;
                    }

                    j = (int)(Bin[++i] * (1 - p) + R * p + 0.5);
                    if (j < 0)
                    {
                        Bin[i] = 0;
                    }
                    else if (j > 255)
                    {
                        Bin[i] = 255;
                    }
                    else
                    {
                        Bin[i] = (byte)j;
                    }

                    j = (int)(Bin[++i] * (1 - p) + A * p + 0.5);
                    if (j < 0)
                    {
                        Bin[i] = 0;
                    }
                    else if (j > 255)
                    {
                        Bin[i] = 255;
                    }
                    else
                    {
                        Bin[i] = (byte)j;
                    }
                }

                Marshal.Copy(Bin, 0, Pixels, c);

                using (SKData Data = SKData.Create(Pixels, c))
                {
                    SKImage Result = SKImage.FromPixelData(new SKImageInfo(ImageInfo.Width, ImageInfo.Height, SKColorType.Bgra8888), Data, ImageInfo.RowBytes);
                    Pixels = IntPtr.Zero;

                    return(Result);
                }
            }
            finally
            {
                if (Pixels != IntPtr.Zero)
                {
                    Marshal.FreeCoTaskMem(Pixels);
                }
            }
        }
Example #22
0
        internal SKImage RenderBitmapRgba(double Gamma, double Vibrancy, bool Preview, SKColor?Background)
        {
            int[]    Frequency;
            double[] Reds;
            double[] Greens;
            double[] Blues;

            if (Preview)
            {
                Frequency = (int[])this.frequency.Clone();
                Reds      = (double[])this.reds.Clone();
                Greens    = (double[])this.greens.Clone();
                Blues     = (double[])this.blues.Clone();
            }
            else
            {
                Frequency = this.frequency;
                Reds      = this.reds;
                Greens    = this.greens;
                Blues     = this.blues;
            }

            int Width  = this.width / this.superSampling;
            int Height = this.height / this.superSampling;
            int size   = Width * Height * 4;

            byte[] rgb = new byte[size];
            int    x, y;
            int    dst = 0;
            int    srcY;
            int    src;
            int    si, a;
            int    rowStep = Width * this.superSampling;
            int    rowStep2 = rowStep - this.superSampling;
            int    srcYStep = rowStep * this.superSampling;
            int    dx, dy;
            int    i, j;
            double r, g, b, s, s2;
            int    freq, maxfreq = 0;
            double GammaComponent = Gamma * (1 - Vibrancy) + Vibrancy;
            double GammaAlpha = Gamma * Vibrancy + (1 - Vibrancy);
            bool   HasBg = Background.HasValue;
            byte   BgR, BgG, BgB;

            if (HasBg)
            {
                BgR = Background.Value.Red;
                BgG = Background.Value.Green;
                BgB = Background.Value.Blue;
            }
            else
            {
                BgR = BgG = BgB = 0;
            }

            s2 = Math.Pow(255.0, GammaComponent);

            if (this.superSampling > 1)
            {
                for (y = srcY = 0; y < Height; y++, srcY += srcYStep)
                {
                    for (x = 0, src = srcY; x < Width; x++, src += this.superSampling)
                    {
                        si   = src;
                        r    = g = b = 0.0;
                        freq = 0;

                        for (dy = 0; dy < this.superSampling; dy++)
                        {
                            for (dx = 0; dx < this.superSampling; dx++, si++)
                            {
                                j = Frequency[si];
                                if (j > 0)
                                {
                                    freq += j;
                                    r    += j * Reds[si];
                                    g    += j * Greens[si];
                                    b    += j * Blues[si];
                                }
                            }

                            si += rowStep2;
                        }

                        if (freq == 0)
                        {
                            Frequency[src] = 0;
                        }
                        else
                        {
                            if (freq > maxfreq)
                            {
                                maxfreq = freq;
                            }

                            s = s2 / freq;
                            Frequency[src] = freq;
                            Reds[src]      = r * s;
                            Greens[src]    = g * s;
                            Blues[src]     = b * s;
                        }
                    }
                }
            }
            else
            {
                maxfreq = 0;
                foreach (int F in Frequency)
                {
                    if (F > maxfreq)
                    {
                        maxfreq = F;
                    }
                }
            }

            if (maxfreq == 0)
            {
                s = 1;
            }
            else
            {
                s = Math.Pow(255.0, GammaAlpha) / Math.Log(maxfreq);
            }

            GammaComponent = 1.0 / GammaComponent;
            GammaAlpha     = 1.0 / GammaAlpha;

            if (Vibrancy == 1)          // Only gamma correction on the alpha-channel
            {
                for (y = srcY = 0; y < Height; y++, srcY += srcYStep)
                {
                    for (x = 0, src = srcY; x < Width; x++, src += this.superSampling)
                    {
                        i = Frequency[src];

                        if (i == 0)
                        {
                            if (HasBg)
                            {
                                rgb[dst++] = BgB;
                                rgb[dst++] = BgG;
                                rgb[dst++] = BgR;
                                rgb[dst++] = 0xff;
                            }
                            else
                            {
                                rgb[dst++] = 0;
                                rgb[dst++] = 0;
                                rgb[dst++] = 0;
                                rgb[dst++] = 0;
                            }
                        }
                        else
                        {
                            if (HasBg)
                            {
                                a = (int)(Math.Pow(Math.Log(i) * s, GammaAlpha));

                                si = (int)Blues[src];
                                si = (si * a + BgB * (255 - a) + 128) / 255;
                                if (si < 0)
                                {
                                    rgb[dst++] = 0;
                                }
                                else if (si > 255)
                                {
                                    rgb[dst++] = 255;
                                }
                                else
                                {
                                    rgb[dst++] = (byte)si;
                                }

                                si = (int)Greens[src];
                                si = (si * a + BgG * (255 - a) + 128) / 255;
                                if (si < 0)
                                {
                                    rgb[dst++] = 0;
                                }
                                else if (si > 255)
                                {
                                    rgb[dst++] = 255;
                                }
                                else
                                {
                                    rgb[dst++] = (byte)si;
                                }

                                si = (int)Reds[src];
                                si = (si * a + BgR * (255 - a) + 128) / 255;
                                if (si < 0)
                                {
                                    rgb[dst++] = 0;
                                }
                                else if (si > 255)
                                {
                                    rgb[dst++] = 255;
                                }
                                else
                                {
                                    rgb[dst++] = (byte)si;
                                }

                                rgb[dst++] = 255;
                            }
                            else
                            {
                                si = (int)Blues[src];
                                if (si < 0)
                                {
                                    rgb[dst++] = 0;
                                }
                                else if (si > 255)
                                {
                                    rgb[dst++] = 255;
                                }
                                else
                                {
                                    rgb[dst++] = (byte)si;
                                }

                                si = (int)Greens[src];
                                if (si < 0)
                                {
                                    rgb[dst++] = 0;
                                }
                                else if (si > 255)
                                {
                                    rgb[dst++] = 255;
                                }
                                else
                                {
                                    rgb[dst++] = (byte)si;
                                }

                                si = (int)Reds[src];
                                if (si < 0)
                                {
                                    rgb[dst++] = 0;
                                }
                                else if (si > 255)
                                {
                                    rgb[dst++] = 255;
                                }
                                else
                                {
                                    rgb[dst++] = (byte)si;
                                }

                                a = (int)(Math.Pow(Math.Log(i) * s, GammaAlpha));
                                if (a < 0)
                                {
                                    rgb[dst++] = 0;
                                }
                                else if (a > 255)
                                {
                                    rgb[dst++] = 255;
                                }
                                else
                                {
                                    rgb[dst++] = (byte)a;
                                }
                            }
                        }
                    }
                }
            }
            else if (Vibrancy == 0)     // Only gamma correction on the individual components.
            {
                for (y = srcY = 0; y < Height; y++, srcY += srcYStep)
                {
                    for (x = 0, src = srcY; x < Width; x++, src += this.superSampling)
                    {
                        i = Frequency[src];

                        if (i == 0)
                        {
                            if (HasBg)
                            {
                                rgb[dst++] = BgB;
                                rgb[dst++] = BgG;
                                rgb[dst++] = BgR;
                                rgb[dst++] = 0xff;
                            }
                            else
                            {
                                rgb[dst++] = 0;
                                rgb[dst++] = 0;
                                rgb[dst++] = 0;
                                rgb[dst++] = 0;
                            }
                        }
                        else
                        {
                            if (HasBg)
                            {
                                a = (int)(Math.Log(i) * s);

                                si = (int)Math.Pow(Blues[src], GammaComponent);
                                si = (si * a + BgB * (255 - a) + 128) / 255;
                                if (si < 0)
                                {
                                    rgb[dst++] = 0;
                                }
                                else if (si > 255)
                                {
                                    rgb[dst++] = 255;
                                }
                                else
                                {
                                    rgb[dst++] = (byte)si;
                                }

                                si = (int)Math.Pow(Greens[src], GammaComponent);
                                si = (si * a + BgG * (255 - a) + 128) / 255;
                                if (si < 0)
                                {
                                    rgb[dst++] = 0;
                                }
                                else if (si > 255)
                                {
                                    rgb[dst++] = 255;
                                }
                                else
                                {
                                    rgb[dst++] = (byte)si;
                                }

                                si = (int)Math.Pow(Reds[src], GammaComponent);
                                si = (si * a + BgR * (255 - a) + 128) / 255;
                                if (si < 0)
                                {
                                    rgb[dst++] = 0;
                                }
                                else if (si > 255)
                                {
                                    rgb[dst++] = 255;
                                }
                                else
                                {
                                    rgb[dst++] = (byte)si;
                                }

                                rgb[dst++] = 255;
                            }
                            else
                            {
                                si = (int)Math.Pow(Blues[src], GammaComponent);
                                if (si < 0)
                                {
                                    rgb[dst++] = 0;
                                }
                                else if (si > 255)
                                {
                                    rgb[dst++] = 255;
                                }
                                else
                                {
                                    rgb[dst++] = (byte)si;
                                }

                                si = (int)Math.Pow(Greens[src], GammaComponent);
                                if (si < 0)
                                {
                                    rgb[dst++] = 0;
                                }
                                else if (si > 255)
                                {
                                    rgb[dst++] = 255;
                                }
                                else
                                {
                                    rgb[dst++] = (byte)si;
                                }

                                si = (int)Math.Pow(Reds[src], GammaComponent);
                                if (si < 0)
                                {
                                    rgb[dst++] = 0;
                                }
                                else if (si > 255)
                                {
                                    rgb[dst++] = 255;
                                }
                                else
                                {
                                    rgb[dst++] = (byte)si;
                                }

                                a = (int)(Math.Log(i) * s);
                                if (a < 0)
                                {
                                    rgb[dst++] = 0;
                                }
                                else if (a > 255)
                                {
                                    rgb[dst++] = 255;
                                }
                                else
                                {
                                    rgb[dst++] = (byte)a;
                                }
                            }
                        }
                    }
                }
            }
            else                        // Interpolated gamma correction on both the components and the alpha channel.
            {
                for (y = srcY = 0; y < Height; y++, srcY += srcYStep)
                {
                    for (x = 0, src = srcY; x < Width; x++, src += this.superSampling)
                    {
                        i = Frequency[src];

                        if (i == 0)
                        {
                            if (HasBg)
                            {
                                rgb[dst++] = BgB;
                                rgb[dst++] = BgG;
                                rgb[dst++] = BgR;
                                rgb[dst++] = 0xff;
                            }
                            else
                            {
                                rgb[dst++] = 0;
                                rgb[dst++] = 0;
                                rgb[dst++] = 0;
                                rgb[dst++] = 0;
                            }
                        }
                        else
                        {
                            if (HasBg)
                            {
                                a = (int)(Math.Pow(Math.Log(i) * s, GammaAlpha));

                                si = (int)Math.Pow(Blues[src], GammaComponent);
                                si = (si * a + BgB * (255 - a) + 128) / 255;
                                if (si < 0)
                                {
                                    rgb[dst++] = 0;
                                }
                                else if (si > 255)
                                {
                                    rgb[dst++] = 255;
                                }
                                else
                                {
                                    rgb[dst++] = (byte)si;
                                }

                                si = (int)Math.Pow(Greens[src], GammaComponent);
                                si = (si * a + BgG * (255 - a) + 128) / 255;
                                if (si < 0)
                                {
                                    rgb[dst++] = 0;
                                }
                                else if (si > 255)
                                {
                                    rgb[dst++] = 255;
                                }
                                else
                                {
                                    rgb[dst++] = (byte)si;
                                }

                                si = (int)Math.Pow(Reds[src], GammaComponent);
                                si = (si * a + BgR * (255 - a) + 128) / 255;
                                if (si < 0)
                                {
                                    rgb[dst++] = 0;
                                }
                                else if (si > 255)
                                {
                                    rgb[dst++] = 255;
                                }
                                else
                                {
                                    rgb[dst++] = (byte)si;
                                }

                                rgb[dst++] = 255;
                            }
                            else
                            {
                                si = (int)Math.Pow(Blues[src], GammaComponent);
                                if (si < 0)
                                {
                                    rgb[dst++] = 0;
                                }
                                else if (si > 255)
                                {
                                    rgb[dst++] = 255;
                                }
                                else
                                {
                                    rgb[dst++] = (byte)si;
                                }

                                si = (int)Math.Pow(Greens[src], GammaComponent);
                                if (si < 0)
                                {
                                    rgb[dst++] = 0;
                                }
                                else if (si > 255)
                                {
                                    rgb[dst++] = 255;
                                }
                                else
                                {
                                    rgb[dst++] = (byte)si;
                                }

                                si = (int)Math.Pow(Reds[src], GammaComponent);
                                if (si < 0)
                                {
                                    rgb[dst++] = 0;
                                }
                                else if (si > 255)
                                {
                                    rgb[dst++] = 255;
                                }
                                else
                                {
                                    rgb[dst++] = (byte)si;
                                }

                                a = (int)(Math.Pow(Math.Log(i) * s, GammaAlpha));
                                if (a < 0)
                                {
                                    rgb[dst++] = 0;
                                }
                                else if (a > 255)
                                {
                                    rgb[dst++] = 255;
                                }
                                else
                                {
                                    rgb[dst++] = (byte)a;
                                }
                            }
                        }
                    }
                }
            }

            using (SKData Data = SKData.Create(new MemoryStream(rgb)))
            {
                return(SKImage.FromPixelData(new SKImageInfo(Width, Height, SKColorType.Bgra8888), Data, Width * 4));
            }
        }
Example #23
0
        internal SKImage RenderBitmapHsl(double Gamma, double LightFactor, bool Preview, SKColor?Background)
        {
            int[]    Frequency;
            double[] Hues;
            double[] Saturations;
            double[] Lights;

            if (Preview)
            {
                Frequency   = (int[])this.frequency.Clone();
                Hues        = (double[])this.reds.Clone();
                Saturations = (double[])this.greens.Clone();
                Lights      = (double[])this.blues.Clone();
            }
            else
            {
                Frequency   = this.frequency;
                Hues        = this.reds;
                Saturations = this.greens;
                Lights      = this.blues;
            }

            int Width  = this.width / this.superSampling;
            int Height = this.height / this.superSampling;
            int size   = Width * Height * 4;

            byte[]  rgb = new byte[size];
            int     x, y;
            int     dst = 0;
            int     srcY;
            int     src;
            int     si;
            int     rowStep = Width * this.superSampling;
            int     rowStep2 = rowStep - this.superSampling;
            int     srcYStep = rowStep * this.superSampling;
            int     SuperSampling2 = this.superSampling * this.superSampling;
            int     dx, dy;
            int     i, j;
            double  H, S, L;
            int     freq, maxfreq = 0;
            long    R2, G2, B2;
            SKColor cl;
            bool    HasBg = Background.HasValue;
            byte    BgR, BgG, BgB;

            if (HasBg)
            {
                BgR = Background.Value.Red;
                BgG = Background.Value.Green;
                BgB = Background.Value.Blue;
            }
            else
            {
                BgR = BgG = BgB = 0;
            }

            maxfreq = 0;
            foreach (int F in Frequency)
            {
                if (F > maxfreq)
                {
                    maxfreq = F;
                }
            }

            Gamma = 1.0 / Gamma;

            if (this.superSampling == 1)
            {
                for (y = srcY = 0; y < Height; y++, srcY += srcYStep)
                {
                    for (x = 0, src = srcY; x < Width; x++, src++)
                    {
                        i = Frequency[src];

                        if (i == 0)
                        {
                            if (HasBg)
                            {
                                rgb[dst++] = BgB;
                                rgb[dst++] = BgG;
                                rgb[dst++] = BgR;
                            }
                            else
                            {
                                rgb[dst++] = 0;
                                rgb[dst++] = 0;
                                rgb[dst++] = 0;
                            }

                            rgb[dst++] = 0xff;
                        }
                        else
                        {
                            H = Hues[src] * 360;
                            S = Math.Pow(Saturations[src], Gamma);
                            L = Math.Pow((Lights[src] * i) / maxfreq, Gamma) * LightFactor;

                            if (S > 1)
                            {
                                S = 1;
                            }

                            if (L > 1)
                            {
                                L = 1;
                            }

                            cl         = Graph.ToColorHSL(H, S, L);
                            rgb[dst++] = cl.Blue;
                            rgb[dst++] = cl.Green;
                            rgb[dst++] = cl.Red;
                            rgb[dst++] = 0xff;
                        }
                    }
                }
            }
            else
            {
                for (y = srcY = 0; y < Height; y++, srcY += srcYStep)
                {
                    for (x = 0, src = srcY; x < Width; x++, src += this.superSampling)
                    {
                        si   = src;
                        R2   = G2 = B2 = 0;
                        freq = 0;

                        for (dy = 0; dy < this.superSampling; dy++)
                        {
                            for (dx = 0; dx < this.superSampling; dx++, si++)
                            {
                                j = Frequency[si];
                                if (j > 0)
                                {
                                    H = Hues[si] * 360;
                                    S = Math.Pow(Saturations[si], Gamma);
                                    L = Math.Pow((Lights[si] * j) / maxfreq, Gamma) * LightFactor;

                                    if (S > 1)
                                    {
                                        S = 1;
                                    }

                                    if (L > 1)
                                    {
                                        L = 1;
                                    }

                                    cl = Graph.ToColorHSL(H, S, L);

                                    freq += j;
                                    R2   += j * cl.Red;
                                    G2   += j * cl.Green;
                                    B2   += j * cl.Blue;
                                }
                            }

                            si += rowStep2;
                        }

                        if (freq == 0)
                        {
                            if (HasBg)
                            {
                                rgb[dst++] = BgB;
                                rgb[dst++] = BgG;
                                rgb[dst++] = BgR;
                            }
                            else
                            {
                                rgb[dst++] = 0;
                                rgb[dst++] = 0;
                                rgb[dst++] = 0;
                            }

                            rgb[dst++] = 0xff;
                        }
                        else
                        {
                            R2 /= freq;
                            if (R2 > 255)
                            {
                                R2 = 255;
                            }

                            G2 /= freq;
                            if (G2 > 255)
                            {
                                G2 = 255;
                            }

                            B2 /= freq;
                            if (B2 > 255)
                            {
                                B2 = 255;
                            }

                            rgb[dst++] = (byte)B2;
                            rgb[dst++] = (byte)G2;
                            rgb[dst++] = (byte)R2;
                            rgb[dst++] = 0xff;
                        }
                    }
                }
            }

            using (SKData Data = SKData.Create(new MemoryStream(rgb)))
            {
                return(SKImage.FromPixelData(new SKImageInfo(Width, Height, SKColorType.Bgra8888), Data, Width * 4));
            }
        }
Example #24
0
        private static SKBitmap LoadTga(string file)
        {
            SKColorType colorType;

            using (var image = Pfim.Pfim.FromFile(file))
            {
                var newData    = image.Data;
                var newDataLen = image.DataLen;
                var stride     = image.Stride;
                switch (image.Format)
                {
                case ImageFormat.Rgb8:
                    colorType = SKColorType.Gray8;
                    break;

                case ImageFormat.R5g6b5:
                    // color channels still need to be swapped
                    colorType = SKColorType.Rgb565;
                    break;

                case ImageFormat.Rgba16:
                    // color channels still need to be swapped
                    colorType = SKColorType.Argb4444;
                    break;

                case ImageFormat.Rgb24:
                    // Skia has no 24bit pixels, so we upscale to 32bit
                    var pixels = image.DataLen / 3;
                    newDataLen = pixels * 4;
                    newData    = new byte[newDataLen];
                    for (int i = 0; i < pixels; i++)
                    {
                        newData[i * 4]     = image.Data[i * 3];
                        newData[i * 4 + 1] = image.Data[i * 3 + 1];
                        newData[i * 4 + 2] = image.Data[i * 3 + 2];
                        newData[i * 4 + 3] = 255;
                    }

                    stride    = image.Width * 4;
                    colorType = SKColorType.Bgra8888;
                    break;

                case ImageFormat.Rgba32:
                    colorType = SKColorType.Bgra8888;
                    break;

                default:
                    throw new ArgumentException($"Skia unable to interpret pfim format: {image.Format}");
                }

                var imageInfo = new SKImageInfo(image.Width, image.Height, colorType);
                var handle    = GCHandle.Alloc(newData, GCHandleType.Pinned);
                var ptr       = Marshal.UnsafeAddrOfPinnedArrayElement(newData, 0);
                using (var data = SKData.Create(ptr, newDataLen, (address, context) => handle.Free()))
                    using (var skImage = SKImage.FromPixelData(imageInfo, data, stride))
                    {
                        var bitmap = SKBitmap.FromImage(skImage);
                        return(bitmap);
                    }
            }
        }