/// <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); } } }
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)); } }
/// <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); }
/// <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); }
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)); } }
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); }
/// <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)); }
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)); } }
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)); } }
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)); } }
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)); } }
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)); } }
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)); } }
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)); } }
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)); } }
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"); } } }
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)); } }
/// <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); } } }
/// <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); } } }
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)); } }
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)); } }
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); } } }